---
agentTools:
  projectIndex: https://developers.pipefy.com/llms.txt
---

# Make API calls

With this functionality, you can use our GraphQL to make API calls

`p.query()` and `p.mutation()` give your app the whole [Pipefy GraphQL API](https://developers.pipefy.com/reference/what-is-graphql) from inside its iframe — no tokens to manage, no CORS to configure. Use them for anything the [context functions](https://developers.pipefy.com/docs/get-pipefy-data) don't cover.

> ⚠️ Calls run as the logged-in user
>
> Both functions execute with the full permissions and access rights of whoever is using your app. Your app is not sandboxed to a narrower scope: if the user can do something in Pipefy, a query from your app can do it too. Only request what your app actually needs, and be deliberate about anything destructive.

## p.query(query, variables)

Makes a GraphQL query using the permissions and access rights of the currently authenticated user. To learn more about our queries, visit [our documentation](https://developers.pipefy.com/reference/what-is-graphql).

### Parameters

`query`: a GraphQL query. It accepts queries with operation names, but only ones whose operation type is `query`. You can learn more about operation names in the [GraphQL official documentation](https://graphql.org/learn/queries/#operation-name). Mutations are not accepted — use [`p.mutation()`](#pmutationmutation-variables) for those.

`variables` (optional): queries with operation names can receive variables. You can learn more about them [here](https://graphql.org/learn/queries/#variables).

If you want to test a query, use our [interactive GraphQL playground](https://app.pipefy.com/graphiql).

### Returns

A `Promise` containing the result of your API call. You can learn more about promises in the [MDN documentation page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).

Once the promise resolves, the result object may contain `data` and `errors`. A response can contain **both** — a partial success — because the query runs with `errorPolicy: 'all'`. Check for `errors` even when `data` is present; see [Call with error and data](#query-example-calls) below. There's more on error shapes in [Status and error handling](https://developers.pipefy.com/reference/status-and-error-handling#error-handling).

The promise resolves even when the call fails outright — see [Checking for errors](#query-example-calls).

### Query example calls

**Simple call**

```javascript
// Returns the ID of the logged user
p.query('{ me { id } }').then(function(result) {
  console.log(result) // { data: { me: { id: "123", __typename: "User" } } }
});
```

**Call with operation name**

```javascript
// Returns the title of a card
const cardTitleQuery = `
query CardTitle {
  card(id: 1234) {
    title
  }
}`;

p.query(cardTitleQuery).then(function(result) {
  console.log(result) // { data: { card: { title: "My Card", __typename: "Card" } } }
});
```

**Call with variables**

```javascript
// Returns the name of the current pipe
const pipeNameQuery = `
query PipeName($pipeId: ID!) {
  pipe(id: $pipeId) {
    name
  }
}`;

const variables = { pipeId: p.app.pipeId };

p.query(pipeNameQuery, variables).then(function(result) {
  console.log(result) // { data: { pipe: { name: "My Pipe", __typename: "Pipe" } } }
});
```

> ⚠️ Use `p.app.pipeId`, not `p.pipeId`
>
> Both properties exist, and they are not interchangeable. `p.app.pipeId` is the ID the GraphQL API expects, and is what you should pass as a variable. `p.pipeId` carries a short ID on some surfaces, so queries built from it fail with a "not found" error that looks like a permissions problem. The same applies to `p.cardId` — prefer the ID returned by [`p.card()`](https://developers.pipefy.com/docs/get-pipefy-data#pcard).
>
> `p.organizationId` is the organization ID and is safe to pass directly, as in the next example.

**Call with error**

```javascript
// Returns an error
// It can be helpful to check those errors when making your implementation

const userIdQuery = 'me { id } }' // Query missing a curly bracket

p.query(userIdQuery).then(function(result) {
  console.log(result) // { errors: "Error: GraphQLError: Syntax Error: Unexpected Name "me"" }
});
```

**Call with error and data**

```javascript
// Returns the org name, but not its members, because the user doesn't have permission to see it
const orgNameAndMembersQuery = `
query OrgNameAndMembers($orgId: ID!) {
  organization(id: $orgId) {
    name
    orgMembers {
      nodes {
        name
      }
    }
  }
}`;

const variables = { orgId: p.organizationId };

p.query(orgNameAndMembersQuery, variables).then(function (result) {
  console.log(result);
  /*
  { data: { organization: { name: "My Org", orgMembers: null, __typename: "Organization" } },
  errors: [ { message: "Permission denied" ... } ] }
  */
});
```

**Checking for errors**

> ⚠️ These promises never reject
>
> `p.query()` and `p.mutation()` catch everything internally — including network failures and expired sessions — and hand it back as `errors` on a **resolved** result. A `.catch()` will never fire, so error handling that relies on it silently does nothing. Always inspect `result.errors`.

```javascript
p.query('{ me { id } }').then(function (result) {
  if (result.errors) {
    // Covers GraphQL errors, permission denials, and transport failures alike
    console.error('Query failed', result.errors);
    p.showNotification('Could not load your user', 'error');
    return;
  }

  console.log(result.data.me.id);
});
```

Note that `errors` is not one consistent shape: a GraphQL response gives you an **array** of error objects, while a thrown transport error gives you a single `Error`. Treat it as truthy-or-not rather than always indexing into it.

## p.mutation(mutation, variables)

Makes a GraphQL mutation using the permissions and access rights of the currently authenticated user.

### Parameters

`mutation`: a GraphQL mutation. It accepts mutations with operation names, but only ones whose operation type is `mutation`. You can learn more about operation names in the [GraphQL official documentation](https://graphql.org/learn/queries/#operation-name). Queries are not accepted — use [`p.query()`](#pqueryquery-variables) for those.

`variables` (optional): mutations with operation names can receive variables. You can learn more about them [here](https://graphql.org/learn/queries/#variables).

If you want to test a mutation, use our [interactive GraphQL playground](https://app.pipefy.com/graphiql).

### Returns

A `Promise` containing the result of your API call, with the same `data`/`errors` shape as `p.query()`.

### Mutation example calls

**Simple call**

```javascript
// Creates a card and returns its id
const createCardMutation = `
mutation {
  createCard(input: {pipe_id: ${p.app.pipeId}, title: "Novo card"}) {
    card {
      id
    }
  }
}`;
p.mutation(createCardMutation).then(function (result) {
  console.log(result);
  /* { data: { createCard: { card: { id: "12", __typename: "Card" } },
  "__typename": "CreateCardPayload" } */
});
```

**Call with operation name**

```javascript
// Deletes a card and returns if the mutation was successful or not
const deleteCardMutation = `
mutation deleteCard {
  deleteCard(input: { id: 1234 }) {
    success
  }
}`;
p.mutation(deleteCardMutation).then(function (result) {
  console.log(result);
  // { data: { deleteCard: { success: true, __typename: "DeleteCardPayload" } } }
});
```

**Call with variables**

Prefer variables over string interpolation for anything that comes from user input — interpolating unescaped values into a mutation string breaks on quotes and newlines:

```javascript
const createCardMutation = `
mutation CreateCard($pipeId: ID!, $title: String!) {
  createCard(input: { pipe_id: $pipeId, title: $title }) {
    card { id }
  }
}`;

const variables = { pipeId: p.app.pipeId, title: userProvidedTitle };

p.mutation(createCardMutation, variables).then(function (result) {
  if (result.errors) {
    p.showNotification('Could not create the card', 'error');
    return;
  }
  p.showNotification('Card created', 'success');
});
```

**Other calls**

To learn how to use variables and the error object, see the [query examples](#query-example-calls) above — the shapes are identical.

## See also

* [Creating calls with GraphQL](https://developers.pipefy.com/reference/creating-calls-with-graphql) — query and mutation structure
* [Limits and best practices](https://developers.pipefy.com/reference/limits-and-best-practices) — rate limits and complexity budgets
* [What is GraphQL](https://developers.pipefy.com/reference/what-is-graphql) — start here if GraphQL is new to you
* [Status and error handling](https://developers.pipefy.com/reference/status-and-error-handling#error-handling) — error shapes and status codes
* [Get Pipefy data](https://developers.pipefy.com/docs/get-pipefy-data) — cheaper, context-aware reads that need no query