Getting Started

Requesting Access

To access the GraphQL API, you'll first need your API key. As an Ad Dashboard user, you can find this key at https://dashboard.tapjoy.com/reporting/api.

If instead you use the LTV Platform, you will need the "GraphQL API Key", which can be found on the LTV Platform. This key can be found by selecting an App -> Settings -> App Settings -> App Info -> API Keys:

Authentication

Requests are authenticated using a standard two-legged OAuth2 flow. An access token is requested using the API Key and the resulting access token is used to authenticate against future requests.

Access tokens have a 1-hour lifetime and cannot be refreshed. Once a token expires you simply request a new one with your API Key.

To request an access token you must send a POST request with an Authorization header using your API Key. If the credentials are valid the response will include an access token and the number of seconds until the token expires.

Example request:

POST /v1/oauth2/token
Host: api.tapjoy.com
Authorization: Basic <API Key>
curl -H "Authorization: Basic <API Key>" -X POST https://api.tapjoy.com/v1/oauth2/token
require 'json'
require 'net/https'

api_key = "<API Key>"

http = Net::HTTP.new('api.tapjoy.com', 443)
http.use_ssl = true

request = Net::HTTP::Post.new('/v1/oauth2/token')
request['Authorization'] = "Basic #{api_key}"
response = http.request(request)
oauth = JSON.parse(response.body)
access_token = oauth['access_token']

Successful response (200 OK):

{
  "access_token": "token_string",
  "token_type": "bearer",
  "expires_in": 3600,
  "refresh_token": null
}

Unsuccessful response (401 Unauthorized):

{
  "error": "Unauthorized"
}

GraphQL Endpoint

The GraphQL API has a single endpoint:

https://api.tapjoy.com/graphql

The endpoint remains the same regardless of the operation being performed.

Communicating with GraphQL

Once you have an access token, requests can be made to the GraphQL API. To form a request for the GraphQL API, a JSON-encoded body is provided via an HTTP POST regardless of whether you're executing a query or mutation.

Example Request:

POST /graphql
Host: api.tapjoy.com
Authorization: Bearer <OAuth Token>

{
  "query": "query { user { firstName } }"
}
curl -H "Authorization: Bearer <OAuth Token>" -X POST -d "\
{\
  \"query\": \"query { user { firstName } }\"\
}\
" https://api.tapjoy.com/graphql
require 'json'
require 'net/https'

access_token = "<OAuth Token>"

query = <<~END
query {
  user {
    firstName
  }
}
END
json = JSON.dump({query: query})

http = Net::HTTP.new('api.tapjoy.com', 443)
http.use_ssl = true

request = Net::HTTP::Post.new('/graphql')
request['Authorization'] = "Bearer #{access_token}"
request.body = json
response = http.request(request)

result = JSON.parse(response.body)
data = result['data']
errors = result['errors']

Working with errors

There are several categories of errors that can be encountered when using the GraphQL API:

  1. Server / network errors
  2. Authentication / Authorization errors
  3. Query syntax errors
  4. Data validation errors

To ensure that your system is properly integrated, you will need to consider how your system should handle each of these categories of errors.

Each category described below will use the following query for context:

query {
  user {
    firstName
    lastName
  }
}

Server / network errors

Occasionally you may encounter unrecoverable server / network errors with the API. In these cases, you will receive the proper http status code for the scenario you're encountering. For example, if there is problem in our API preventing queries from executing, then you'll receive an HTTP response with a 500 status code.

The best way to handle this scenario is to employ a retry behavior with exponential back-off.

Authentication / Authorization errors

Authentication / authorization errors can occur for a few reasons:

  • Your OAuth token is expire
  • Your OAuth token is invalid
  • We are incurring issues with our underlying authentication system

In these types of situations, you'll receive a HTTP 200 OK response with the following data:

{
  "errors": [
    {
      "message": "Authentication could not be verified. Please try again later.",
      "code": 403
    }
  ]
}
  • message - A human-readable description of the error
  • code - A GraphQL status code that corresponds to HTTP status codes

The best way to handle this scenario is to request a new access token and retry the request.

Query syntax errors

All queries and mutations are verified upfront that they are syntactically correct and follow the described data schema. If the provided query does not pass all schema validations, then you'll receive a HTTP 200 OK response with the following data:

{
  "errors": [
    {
      "message": "Field 'user' doesn't exist on type 'Query'",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "fields": [
        "query",
        "user"
      ]
    }
  ]
}
  • message - A human-readable description of the error
  • locations - The locations of the syntax error
  • fields - The fields affect by the syntax error

The best way to handle this scenario is to refer to the API documentation and test your query in the Interactive Explorer.

Data validation errors

Although you may provide a mutation that is properly constructed with all of the required fields, it can still fail due to business validations. For example, let's say you're an advertiser changing a bid to below the minimum for your AdSet like so:

mutation {
  updateAdSet(input: {
    id: "00000000-0000-0000-0000-000000000000",
    bidding: {amount: 10000}
  }) {
    adSet {
      id
    }
  }
}

In that scenario, you'll receive a HTTP 200 OK response with the following data:

{
  "data": {
    "updateAdSet": null
  },
  "errors": [
    {
      "message": "Amount is below the minimum (20000 micros)",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "updateAdSet",
        "input",
        "bidding",
        "amount"
      ],
      "code": 422
    }
  ]
}
  • message - A human-readable description of the error
  • locations - The locations of the validation error
  • path - A fully-qualified reference to the field that was determined to be invalid
  • code - A GraphQL status code that corresponds to HTTP status codes

The best way to handle this scenario is to present the error message alongside the corresponding field (via the path) to the user.


Please contact your Tapjoy AM or support if you have any questions.