Getting Started

GraphQL, developed by Facebook, is an open-source data query and manipulation language for APIs. In addition to the traditional REST API, Parse Server automatically generates a GraphQL API based on your current application schema.

The easiest way to run the Parse GraphQL Server is using the CLI:

$ npm install -g parse-server mongodb-runner
$ mongodb-runner start
$ parse-server --appId APPLICATION_ID --masterKey MASTER_KEY --databaseURI mongodb://localhost/test --publicServerURL http://localhost:1337/parse --mountGraphQL --mountPlayground

Notes:

  • Run parse-server --help or refer to Parse Server Options for a complete list of Parse Server configuration options.
  • ⚠️ Please do not use --mountPlayground option in production as anyone could access your API Playground and read or change your application’s data. Parse Dashboard has a built-in GraphQL Playground and it is the recommended option for production apps.
  • ⚠️ The Parse GraphQL beta implementation is fully functional but discussions are taking place on how to improve it. So new versions of Parse Server can bring breaking changes to the current API.

After running the CLI command, you should have something like this in your terminal:

Parse GraphQL Server

Since you have already started your Parse GraphQL Server, you can now visit http://localhost:1337/playground in your web browser to start playing with your GraphQL API.

GraphQL Playground

Using Docker

You can also run the Parse GraphQL API inside a Docker container:

$ git clone https://github.com/parse-community/parse-server
$ cd parse-server
$ docker build --tag parse-server .
$ docker run --name my-mongo -d mongo
$ docker run --name my-parse-server --link my-mongo:mongo -p 1337:1337 -d parse-server --appId APPLICATION_ID --masterKey MASTER_KEY --databaseURI mongodb://mongo/test --publicServerURL http://localhost:1337/parse --mountGraphQL --mountPlayground

After starting the server, you can visit http://localhost:1337/playground in your browser to start playing with your GraphQL API.

⚠️ Please do not use --mountPlayground option in production as anyone could access your API Playground and read or change your application’s data. Parse Dashboard has a built-in GraphQL Playground and it is the recommended option for production apps.

Using Express.js

You can also mount the GraphQL API in an Express.js application together with the REST API or solo. You first need to create a new project and install the required dependencies:

$ mkdir my-app
$ cd my-app
$ npm install parse-server express --save

Then, create an index.js file with the following content:

const express = require('express');
const { default: ParseServer, ParseGraphQLServer } = require('parse-server');

const app = express();

const parseServer = new ParseServer({
  databaseURI: 'mongodb://localhost:27017/test',
  appId: 'APPLICATION_ID',
  masterKey: 'MASTER_KEY',
  serverURL: 'http://localhost:1337/parse',
  publicServerURL: 'http://localhost:1337/parse'
});

const parseGraphQLServer = new ParseGraphQLServer(
  parseServer,
  {
    graphQLPath: '/graphql',
    playgroundPath: '/playground'
  }
);

app.use('/parse', parseServer.app); // (Optional) Mounts the REST API
parseGraphQLServer.applyGraphQL(app); // Mounts the GraphQL API
parseGraphQLServer.applyPlayground(app); // (Optional) Mounts the GraphQL Playground - do NOT use in Production

app.listen(1337, function() {
  console.log('REST API running on http://localhost:1337/parse');
  console.log('GraphQL API running on http://localhost:1337/graphql');
  console.log('GraphQL Playground running on http://localhost:1337/playground');
});

And finally start your app:

$ npx mongodb-runner start
$ node index.js

After starting the app, you can visit http://localhost:1337/playground in your browser to start playing with your GraphQL API.

⚠️ Please do not mount the GraphQL Playground in production as anyone could access your API Playground and read or change your application’s data. Parse Dashboard has a built-in GraphQL Playground and it is the recommended option for production apps.

Running Parse Dashboard

Parse Dashboard is a standalone dashboard for managing your Parse Server apps, including your objects’ schema and data, logs, jobs, and push notifications. Parse Dashboard also has a built-in GraphQL Playground that you can use to play around with your auto-generated Parse GraphQL API. It is the recommended option for production applications.

The easiest way to run the Parse Dashboard is through its CLI:

$ npm install -g parse-dashboard
$ parse-dashboard --dev --appId APPLICATION_ID --masterKey MASTER_KEY --serverURL "http://localhost:1337/parse" --graphQLServerURL "http://localhost:1337/graphql" --appName MyAppName

After starting the dashboard, you can visit http://0.0.0.0:4040/apps/MyAppName/api_console/graphql in your browser:

Parse Dashboard GraphQL Playground

To learn more about Parse Dashboard and its setup options, please visit Parse Dashboard Repository.

Want to contribute to this doc? Edit this section.

Your First Query - Health Check

Now that you have set up your GraphQL environment, it is time to run your first query. Execute the following code in your GraphQL Playground to check your API’s health:

query Health {
  health
}

You should receive the following response:

{
  "data": {
    "health": true
  }
}
Want to contribute to this doc? Edit this section.

Creating your first class

Since your application does not have any schema yet, you can use the createClass mutation to create your first class. Run the following:

mutation CreateClass {
  createClass(
    name: "GameScore"
    schemaFields: {
      addStrings: [{ name: "playerName" }]
      addNumbers: [{ name: "score" }]
      addBooleans: [{ name: "cheatMode" }]
    }
  ) {
    name
    schemaFields {
      name
      __typename
    }
  }
}

You should receive the following response:

{
  "data": {
    "createClass": {
      "name": "GameScore",
      "schemaFields": [
        {
          "name": "objectId",
          "__typename": "SchemaStringField"
        },
        {
          "name": "updatedAt",
          "__typename": "SchemaDateField"
        },
        {
          "name": "createdAt",
          "__typename": "SchemaDateField"
        },
        {
          "name": "playerName",
          "__typename": "SchemaStringField"
        },
        {
          "name": "score",
          "__typename": "SchemaNumberField"
        },
        {
          "name": "cheatMode",
          "__typename": "SchemaBooleanField"
        },
        {
          "name": "ACL",
          "__typename": "SchemaACLField"
        }
      ]
    }
  }
}

Parse Server learned from the first class that you created and now you have the GameScore class in your schema. You can now start using the automatically generated operations!

Want to contribute to this doc? Edit this section.

Objects

Creating Objects

For each class of your application’s schema, Parse Server automatically generates a custom mutation for creating this class’ objects through the GraphQL API.

For example, if you have a class named GameScore in the schema, Parse Server automatically generates a new mutation called createGameScore, and you should be able to run the code below in your GraphQL Playground:

mutation CreateGameScore {
  createGameScore(
    fields: {
      playerName: "Sean Plott"
      score: 1337
      cheatMode: false
    }
  ) {
    id
    updatedAt
    createdAt
    playerName
    score
    cheatMode
    ACL
  }
}

The code above should resolve to something similar to this:

{
  "data": {
    "createGameScore": {
      "id": "XN75D94OBD",
      "updatedAt": "2019-09-17T06:50:26.357Z",
      "createdAt": "2019-09-17T06:50:26.357Z",
      "playerName": "Sean Plott",
      "score": 1337,
      "cheatMode": false,
      "ACL": null
    }
  }
}

Getting an Object

For each class of your application’s schema, Parse Server automatically generates a custom query for getting this class’ objects through the GraphQL API.

For example, if you have a class named GameScore in the schema, Parse Server automatically generates a new query called gameScore, and you should be able to run the code below in your GraphQL Playground:

query GameScore {
  gameScore(id: "XN75D94OBD") {
    id
    updatedAt
    createdAt
    playerName
    score
    cheatMode
    ACL
  }
}

The code above should resolve to something similar to this:

{
  "data": {
    "gameScore": {
      "id": "XN75D94OBD",
      "updatedAt": "2019-09-17T06:50:26.357Z",
      "createdAt": "2019-09-17T06:50:26.357Z",
      "playerName": "Sean Plott",
      "score": 1337,
      "cheatMode": false,
      "ACL": null
    }
  }
}

Finding Objects

For each class of your application’s schema, Parse Server automatically generates a custom query for finding this class’ objects through the GraphQL API.

For example, if you have a class named GameScore in the schema, Parse Server automatically generates a new query called gameScores, and you should be able to run the code below in your GraphQL Playground:

query GameScores {
  gameScores {
    count
    results {
      id
      updatedAt
      createdAt
      playerName
      score
      cheatMode
      ACL
    }
  }
}

The code above should resolve to something similar to this:

{
  "data": {
    "gameScores": {
      "count": 2,
      "results": [
        {
          "id": "XN75D94OBD",
          "updatedAt": "2019-09-17T06:50:26.357Z",
          "createdAt": "2019-09-17T06:50:26.357Z",
          "playerName": "Sean Plott",
          "score": 1337,
          "cheatMode": false,
          "ACL": null
        },
        {
          "id": "a7ulpjjuji",
          "updatedAt": "2019-09-17T07:11:28.869Z",
          "createdAt": "2019-09-17T07:11:28.869Z",
          "playerName": "Jang Min Chul",
          "score": 80075,
          "cheatMode": false,
          "ACL": null
        }
      ]
    }
  }
}

Constraints

You can use the where argument to add constraints to a class find query. See the example below:

query ConstraintsExamples {
  gameScores(
    where: { score: { greaterThan: 1500 } }
  ) {
    count
  }
}

The code above should resolve to something similar to this:

{
  "data": {
    "gameScores": {
      "count": 1
    }
  }
}

Order

You can use the order argument to select in which order the results should show up in a class find query. See the example below:

query OrderExamples {
  gameScores(
    where: { cheatMode: { equalTo: false } }
    order: [score_DESC]
  ) {
    results {
      playerName
      score
    }
  }
}

The code above should resolve to something similar to this:

{
  "data": {
    "gameScores": {
      "results": [
        {
          "playerName": "Jang Min Chul",
          "score": 80075
        },
        {
          "playerName": "Sean Plott",
          "score": 1337
        }        
      ]
    }
  }
}

Pagination

You can use the skip and limit arguments to paginate the results in a class find query. See the example below:

query PaginationExamples {
  gameScores(
    where: { cheatMode: { equalTo: false } }
    order: [score_DESC]
    skip: 1
    limit: 1
  ) {
    results {
      playerName
      score
    }
  }
}

The code above should resolve to something similar to this:

{
  "data": {
    "gameScores": {
      "results": [
        {
          "playerName": "Sean Plott",
          "score": 1337
        }
      ]
    }
  }
}

Updating an Object

For each class of your application’s schema, Parse Server automatically generates a custom mutation for updating this class’ objects through the GraphQL API.

For example, if you have a class named GameScore in the schema, Parse Server automatically generates a new mutation called updateGameScore, and you should be able to run the code below in your GraphQL Playground:

mutation UpdateGameScore {
  updateGameScore(
    id: "XN75D94OBD"
    fields: { score: 1400 }
  ) {
    id
    updatedAt
    createdAt
    playerName
    score
    cheatMode
    ACL
  }
}

The code above should resolve to something similar to this:

{
  "data": {
    "updateGameScore": {
      "id": "XN75D94OBD",
      "updatedAt": "2019-09-17T07:25:21.139Z",
      "createdAt": "2019-09-17T06:50:26.357Z",
      "playerName": "Sean Plott",
      "score": 1400,
      "cheatMode": false,
      "ACL": null
    }
  }
}

Deleting an Object

For each class of your application’s schema, Parse Server automatically generates a custom mutation for deleting this class’ objects through the GraphQL API.

For example, if you have a class named GameScore in the schema, Parse Server automatically generates a new mutation called deleteGameScore, and you should be able to run the code below in your GraphQL Playground:

mutation DeleteGameScore {
  deleteGameScore(id: "a7ulpjjuji") {
    id
    updatedAt
    createdAt
    playerName
    score
    cheatMode
    ACL
  }
}

The code above should resolve to something similar to this:

{
  "data": {
    "deleteGameScore": {
      "id": "a7ulpjjuji",
      "updatedAt": "2019-09-17T07:11:28.869Z",
      "createdAt": "2019-09-17T07:11:28.869Z",
      "playerName": "Jang Min Chul",
      "score": 80075,
      "cheatMode": false,
      "ACL": null
    }
  }
}
Want to contribute to this doc? Edit this section.

Users

In general, users have the same features as other objects. The differences are that user objects must have a username and password, the password is automatically encrypted and stored securely, and Parse Server enforces the uniqueness of the username and email fields.

Therefore you can manage users objects using the createUser, user, users, updateUser, and deleteUser operations.

Additionally, you can use the signUp, logIn, and logOut operations, which will be presented in the following sections.

Signing Up

Signing up a new user differs from creating another object in that the username and password fields are required. The password field is handled differently than the others; it is encrypted with bcrypt when stored in the database and never returned to any client request.

You can ask Parse Server to verify user email addresses in your application settings. With this setting enabled, all new user registrations with an email field will generate an email confirmation at that address. You can check whether the user has verified their email with the emailVerified field.

To sign up a new user, use the signUp mutation. For example:

mutation SignUp {
  signUp(fields: {
    username: "somedude"
    password: "Parse_3.9_Rocks!"
  }) {
    id
    updatedAt
    createdAt
    username
    sessionToken
    ACL
  }
}

The code above should resolve to something similar to this:

{
  "data": {
    "signUp": {
      "id": "F8p2yGbq2O",
      "updatedAt": "2019-09-17T07:32:56.425Z",
      "createdAt": "2019-09-17T07:32:56.425Z",
      "username": "somedude",
      "sessionToken": "r:0eaf42db02a3345dbae0c70eae0dc015",
      "ACL": {
        "*": {
          "read": true
        },
        "F8p2yGbq2O": {
          "read": true,
          "write": true
        }
      }
    }
  }
}

Note that a field called sessionToken has been returned. This token can be used to authenticate subsequent operations as this user.

Logging In

After you allow users to sign up, you need to let them log in to their account with a username and password in the future. To do this, use the logIn mutation:

mutation LogIn {
  logIn(
    fields: {
      username: "somedude"
      password: "Parse_3.9_Rocks!"
    }
  ) {
    id
    updatedAt
    createdAt
    username
    sessionToken
    ACL
  }
}

The code above should resolve to something similar to this:

{
  "data": {
    "logIn": {
      "id": "F8p2yGbq2O",
      "updatedAt": "2019-09-17T07:32:56.425Z",
      "createdAt": "2019-09-17T07:32:56.425Z",
      "username": "somedude",
      "sessionToken": "r:905e0ab9ea5ebad18157686fab4af488",
      "ACL": {
        "*": {
          "read": true
        },
        "F8p2yGbq2O": {
          "read": true,
          "write": true
        }
      }
    }
  }
}

Note that, when the user logs in, Parse Server generates a new sessionToken for future operations.

Using Session Token

For authenticating an operation as a specific user, you need to pass the X-Parse-Session-Token header with its valid session token.

You can easily do this in the GraphQL Playground. There is an option called HTTP HEADERS in its bottom left side. Use this option to replace the default X-Parse-Master-Key header by a valid X-Parse-Session-Token header. You should have something like this:

Session Token Header

After setting up the X-Parse-Session-Token header, any operation will run as this user. For example, you can run the code below to validate the session token and return its associated user:

query Viewer {
  viewer {
    id
    updatedAt
    createdAt
    username
    sessionToken
    ACL
  }
}

The code above should resolve to something similar to this:

{
  "data": {
    "viewer": {
      "id": "F8p2yGbq2O",
      "updatedAt": "2019-09-17T07:32:56.425Z",
      "createdAt": "2019-09-17T07:32:56.425Z",
      "username": "somedude",
      "sessionToken": "r:905e0ab9ea5ebad18157686fab4af488",
      "ACL": {
        "*": {
          "read": true
        },
        "F8p2yGbq2O": {
          "read": true,
          "write": true
        }
      }
    }
  }
}

Logging Out

You can log out a user through the logOut mutation. You need to send the X-Parse-Session-Token header and run code like the below example:

mutation LogOut {
  logOut {
    id
    updatedAt
    createdAt
    username
    sessionToken
    ACL
  }
}

The code above should resolve to something similar to this:

{
  "data": {
    "logOut": {
      "id": "F8p2yGbq2O",
      "updatedAt": "2019-09-17T07:32:56.425Z",
      "createdAt": "2019-09-17T07:32:56.425Z",
      "username": "somedude",
      "sessionToken": "r:905e0ab9ea5ebad18157686fab4af488",
      "ACL": {
        "*": {
          "read": true
        },
        "F8p2yGbq2O": {
          "read": true,
          "write": true
        }
      }
    }
  }
}
Want to contribute to this doc? Edit this section.

Customisation

Although we automtically generate a GraphQL schema based on your Parse Server database, we have provided a number of ways in which to configure and extend this schema.

Configuration

Whilst it’s great to simply plug GraphQL into your Parse setup and immediately query any of your existing classes, you may find that this level of exposure is not suitable to your project. We have therefore provided a flexible way to limit which types, queries mutations are exposed within your GraphQL schema.

Configuration Options

By default, no configuration is needed to get GraphQL working with your Parse Server. All of the following settings are completely optional, and can be provided or omitted as desired. To configure your schema, you simply need to provide a valid JSON object with the expected properties as described below:

// The properties with ? are optional

interface ParseGraphQLConfiguration {
  // All classes enabled by default
  // Provide an empty array to disable all classes
  enabledForClasses?: Array<string>;

  // Selectively disable specific classes
  disabledForClasses?: Array<string>;

  // Provide an array of per-class settings
  classConfigs?: Array<{

    // You must provide a className
    // Only provide one config object per class
    className: string;

    type?: {

      // By default, all fields can be sent for
      // a create or update mutation. Use this
      // setting to limit to specific fields.
      inputFields?: {
        create?: Array<string>;
        update?: Array<string>;
      };

      // By default, all fields can be resolved
      // on a get or find query. Use this to limit
      // which fields can be selected.
      outputFields?: Array<string>;

      // By default, all valid fields can be used
      // to filter a query. Use this to limit
      // which fields can be used to constrain a query.
      constraintFields?: Array<string>;

      // By default, all valid fields can be used
      // to sort the results of a query. Use this to
      // limit which fields can be used to sort a query
      // and which direction that sort can be set to.
      sortFields?: {
        field: string;
        asc: boolean;
        desc: boolean;
      }[];
    };

    // By default, a get and find query type is created
    // for all included classes. Use this to disable
    // the available query types for this class.
    query?: {
      get?: boolean;
      find?: boolean;
    };

    // By default, all write mutation types are 
    // exposed for all included classes. Use this to disable
    // the available mutation types for this class.
    mutation?: {
      create?: boolean;
      update?: boolean;
      destroy?: boolean;
    };
  }>
}

Set or Update Configuration

We have provided a public API in ParseGraphQLServer which accepts the above JSON object for setting (and updating) your Parse GraphQL Configuration, setGraphQLConfig:

  const parseGraphQLServer = new ParseGraphQLServer(parseServer, {
    graphQLPath: parseServerConfig.graphQLPath,
    playgroundPath: parseServerConfig.playgroundPath
  });

  const config = {
    // ... ParseGraphQLConfiguration
  };

  await parseGraphQLServer.setGraphQLConfig(config);       

Include or Exclude Classes

By default, all of your Parse classes, including the defaults such as Parse.User, Parse.Session, Parse.Role are added to the schema. You can restrict this using the enabledForClassess or disabledForClassess options, which accepts an array of class names.

In the following example, we limit our GraphQL schema to only expose the default _User class, along with a few custom classes:

{
  "enabledForClasses": ["_User", "Book", "Review", "Comment"],
  "disabledForClasses": null
}

In the following example, we limit our GraphQL schema by hiding some sensitive classes:

{
  // undefined or null results in the default behaviour, i.e. include all classes
  "enabledForClasses": undefined,
  // override the included classes by filtering out the following:
  "disabledForClasses": [ "UserSensitiveData", "ProductOrder", "Invoice" ]
}

Input Types

By default, we enrich the schema by generating a number of Input Types for each class. This, as a healthy side-effect, improves development experience by providing type-completion and docs, though the true purpose is to define exactly what fields are exposed and useable per operation type. You can provide a type setting for any or each of your classes to limit which fields are exposed:

In the following example, we have a custom class called Review where the fields rating and body are allowed on the create mutation, and the field numberOfLikes on the update mutation:

{
  "classConfigs": [
    {
      "className": "Review",
      "type": {
        "inputFields": {
          "create": ["rating", "body"],
          "update": ["numberOfLikes"]
        }
      }
    }
  ]
}

You may decide to restrict which fields can be resolved when getting or finding records from a given class, for example, if you have a class called Video which includes a sensitive field dmcaFlags, you can hide this field by explicitly stating the fields that can be resolved:

{
  "classConfigs": [
    {
      "className": "Video",
      "type": {
        "outputFields": ["name", "author", "numberOfViews",   "comments", "cdnUrl"]
      }
    }
  ]
}

In production-grade environments where performance optimisation is critical, complete control over query filters and sortability is required to ensure that unindexed queries are not executed. For this reason, we provide a way to limit which fields can be used to constrain a query, and which fields (including the direction) can be used to sort that query.

In the following example, we set the fields name and age as the only two that can be used to filter the _User class, and defining the createdAt and age fields the only sortable field whilst disabling the ascending direction on the createdAt field:

{
  "classConfigs": [
    {
      "className": "_User",
      "type": {
         "constraintFields": ["name", "age"],
          "sortFields": [
            {
              "field": "createdAt",
              "desc": true,
              "asc": false
            },
            {
              "field": "age",
              "desc": true,
              "asc": true
            }
          ]
        }
      }
  ]
}

Queries

By default, the schema exposes a get and find operation for each class, for example, get_User and find_User. You can disable either of these for any class in your schema, like so:

{
  "classConfigs": [
    {
      "className": "_User",
      "query": {
        "get": true,
        "find": false
      }  
    },
    {
      "className": "Review",
      "query": {
        "get": false,
        "find": true
      }  
    }
  ]
}

Mutations

By default, the schema exposes a create, update and delete operation for each class, for example, create_User, update_User and delete_User. You can disable any of these mutations for any class in your schema, like so:

{
  "classConfigs": [
    {
      "className": "_User",
      "mutation": {
        "create": true,
        "update": true,
        "destroy": true
      }  
    },
    {
      "className": "Review",
      "mutation": {
        "create": true,
        "update": false,
        "destroy": true
      }  
    }
  ]
}

Note: the delete mutation setting key is named destroy to avoid issues due to delete being a javascript reserved word.

Want to contribute to this doc? Edit this section.

Learning More

If you look at the right side of your GraphQL Playground, you will see the DOCS and SCHEMA menus. They are automatically generated by analyzing your application schema and contain all operations that you can call for your application, including the automatic class queries and mutations. Please refer to them and learn more about everything that you can do with your Parse GraphQL API.

GraphQL Docs

Additionally, the GraphQL Learn Section is a very good source to start learning about the power of the GraphQL language.

Want to contribute to this doc? Edit this section.