New to GraphQL?

If you haven't used GraphQL before, let's get you up to speed quickly. You'll love it!

Most SaaS applications today have REST APIs that allow you to access your data programmatically. REST is easy to learn and widely adopted, but when it comes to more complex data structures, they can be hard to work with. Bunny is built on GraphQL and everything you can do via the user interface can be done via the API.

GraphQL has a number of advantages over REST.

  • Efficient data fetching - In REST, clients often receive fixed data structures, leading to over-fetching (getting more data than needed) or under-fetching (needing multiple requests). GraphQL allows clients to request exactly the data they need in a single query, reducing unnecessary data transfer and improving performance.

  • Strongly typed schema - GraphQL relies on a schema with strict typing, which defines the structure of data and operations. This provides better clarity, validation, and tooling support, e.g., auto-generated documentation and type checking.

  • Flexible queries - Clients can tailor queries to their needs, combining multiple resources in one request. For example, fetching a user’s profile and their recent posts in REST might require separate calls, while GraphQL handles it in one go. This flexibility reduces round-trips and optimizes frontend development.

  • Versioning not required - REST APIs often evolve by creating new versions (e.g., /v1, /v2), which can complicate maintenance. GraphQL’s schema can evolve by adding fields or types without breaking existing queries, as clients only request what they need, reducing the need for versioning.

  • Better developer experience: - Tools like GraphiQL and Altair provide interactive query testing and auto-completion based on the schema. REST lacks such built-in exploration tools, often requiring separate documentation that may fall out of sync.

Queries

Where REST GET requests return entire objects, GraphQL queries specify exactly which fields to return. The query below fetches id and name for account 1.

query {
  account(id: 1) {
    id
    name
  }
}

The data returned from the API is standard JSON.

{
  "data": {
    "account": {
      "id": "1",
      "name": "Acme"
    }
  }
}

Nesting queries

Let's say we also want all contacts for an account. We can do that by nesting the contacts query inside account {}, which is simpler and faster than making multiple REST calls.

query {
  account(id: 1) {
    id
    name
    contacts {
      firstName
      lastName
      email
    }
  }
}

This returns the follwing JSON.

{
  "data": {
    "account": {
      "id": "1",
      "name": "Acme",
      "contacts": [
        {
          "firstName": "Tom",
          "lastName": Jones,
          "email": "tom@example.com"
        }
      ]
    }
  }
}

You can get almost infinitely complex with nested queries. For example, querying an account could also include all its invoices, quotes and subscriptions. This is really the big advantage of GraphQL over REST.

Fetching multiple objects

If we want to get multiple accounts, we can do it using the plural form in the query.

{
  accounts {
    nodes {
      id
      name
    }
  }
}

This returns an array of accounts.

{
  "data": {
    "accounts": {
      "nodes": [
        {
          "id": "19",
          "name": "AA"
        },
        {
          "id": "1",
          "name": "Acme"
        }
      ]
    }
  }
}

And of course we can also nest contacts, deals, invoices etc inside of the accounts.

Filters

{
  accounts(filter: "name begins_with 'Ac'", first: 10) {
    nodes {
      id
      name
    }
  }
}

You can also use AND, OR and grouping with parentheses to make more complex queries.

Mutations

Updating data in GraphQL is done using mutations. The syntax may seem a little complicated at first because of the strong typing, but will quickly get the hang of it. There are several ways of structuring a mutation and the one below is fairly standard.

The attributes being updated are passed in a separate JSON object and the fields inside account {} are the fields you want returned from the API after the update has completed.

mutation accountUpdate($id: ID!, $attributes: AccountAttributes!) {
  accountUpdate(id: $id, attributes: $attributes) {
    account {
      name
    }
  }
}

The JSON object tells the mutation that we are updating account with ID 2 and the attributes hash contains the fields and values we want to update.

{
  "id": "2",
  "attributes": {
    "name": "BBB"
  }
}

Conclusion

As you can probably tell, GraphQL is very powerful and provides an excellent developer experience. Plus, it's great for doing complex ad-hoc queries for non-technical users.

Last updated

Was this helpful?