Global Fishing Watch API
API v3General API Documentation

Errors

GFW API status codes, error-response format, and example error payloads.

The GFW API uses standard HTTP status codes. This page lists them, the response format for errors, and example payloads. For authentication-specific errors, see Authentication.

The GFW API uses the following error codes:

RangeDescription
2XXSuccessful execution
4XXError on the client side
5XXErrors on the server side
CodeMeaning
200OKAY - The request has succeeded.
202Accepted - The request has been accepted for processing, but the processing has not been completed.
204No content - The server has successfully fulfilled the request and that there is no additional content to send in the response payload body.For example when you ask for an empty tile in /4wings/tile/heatmap/
401Unauthorized - Your API Access Token is wrong or your don't have permissions to access that dataset.
403Forbidden - The server understood the request but refuses to authorize it.
404Not Found - The specified data could not be found.
422Unprocessable Entity -The server understands the content type of the request entity, and the syntax of the request entity is correct but was unable to process the contained instructions. For example, this error condition may occur if a a user requests in /4wings/tile/heatmap/ a zoom greater than 12 since it is semantically erroneous, we only support up to zoom level 12.
429Too Many Requests - The server received more request that the user can do. For example, this error condition may occur if a user tries to do several reports at the same time.
503Service Unavailable - We're temporarily offline for maintenance. Please try again later or contact us in apis@globalfishingwatch.org

Error Code Examples

If you are asking for a wrong API dataset, you get this error:

{
  "statusCode": 404,
  "error": "Not Found",
  "messages": [
    {
      "title": "Not Found",
      "detail": "Dataset with id public-global-fishing-effort:latest not found"
    }
  ]
}

If you are missing one mandatory field, for a example 'Query', you get this error:

{
  "statusCode": 422,
  "error": "Unprocessable Entity",
  "messages": [
    {
      "title": "Query",
      "detail": "Query param dataset is required"
    }
  ]
}

If you have insufficient permissions, you get this error:

{
  "statusCode": 403,
  "error": "Forbidden",
  "messages": [
    {
      "title": "Forbidden",
      "detail": "Insufficient permissions for public-global-fishing-effort:latest datasets"
    }
  ]
}

If you send zoom > 12 in /4wings/tile/heatmap/, you get this error:

{
  "statusCode": 422,
  "error": "Unprocessable Entity",
  "messages": [
    {
      "title": "z",
      "detail": "The tiler does not support zoom levels greater than 12"
    }
  ]
}

If you send a report at the same time that you doing other report, you get this error:

{
  "statusCode": 429,
  "error": "Too Many Requests",
  "messages": [
    {
      "title": "Too Many Requests",
      "detail": "You can only generate one report at the same time. If you need this feature, contact us"
    }
  ]
}

If you try to generate a style url (/v3/4wings/generate-png) and it doesn't exist data for the filters.`, you get this error:

{
  "statusCode": 204
}

In 4Wings Report API, if you are sending a custom polygon that is too large, you get this error in html. In this case, we recommend sending a region id, see more details here

<html>
  <head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
    <title>413 Request Entity Too Large</title>
  </head>
  <body text="#000000" bgcolor="#ffffff">
    <h1>Error: Request Entity Too Large</h1>
    <h2>Your client issued a request that was too large.</h2>
    <h2>
      <script>
        ;(function () {
          /*

 Copyright The Closure Library Authors.
 SPDX-License-Identifier: Apache-2.0
*/
          var c = function (a, d, b) {
            a = a + '=deleted; path=' + d
            null != b && (a += '; domain=' + b)
            document.cookie = a + '; expires=Thu, 01 Jan 1970 00:00:00 GMT'
          }
          var g = function (a) {
            var d = e,
              b = location.hostname
            c(d, a, null)
            c(d, a, b)
            for (var f = 0; ;) {
              f = b.indexOf('.', f + 1)
              if (0 > f) break
              c(d, a, b.substring(f + 1))
            }
          }
          var h
          if (4e3 < unescape(encodeURI(document.cookie)).length) {
            for (var k = document.cookie.split(';'), l = [], m = 0; m < k.length; m++) {
              var n = k[m].match(/^\s*([^=]+)/)
              n && l.push(n[1])
            }
            for (var p = 0; p < l.length; p++) {
              var e = l[p]
              g('/')
              for (var q = location.pathname, r = 0; ;) {
                r = q.indexOf('/', r + 1)
                if (0 > r) break
                var t = q.substring(0, r)
                g(t)
                g(t + '/')
              }
              '/' != q.charAt(q.length - 1) && (g(q), g(q + '/'))
            }
            h = !0
          } else h = !1
          h &&
            setTimeout(function () {
              if (history.replaceState) {
                var a = location.href
                history.replaceState(null, '', '/')
                location.replace(a)
              }
            }, 1e3)
        })()
      </script>
    </h2>
  </body>
</html>

Most error responses have this format, except when the request entity is too large (see example on the right):

{
  "statusCode": "4XXX or 5XXX",
  "messages": [
    {
      "title": "[Title]",
      "detail": "[Detail]"
    }
  ],
  "error": "[Generic error]"
}