DEVELOPER GUIDE

View as Markdown

Beta

Error Handling

How the Session and Workflow APIs report errors, how to branch on them, and the limits worth knowing before you go live.

How errors arrive

An error arrives in one of two JSON shapes, and which one you get follows which layer answered, not the status code.

Content-Type Body Read
application/json The messages envelope. messages[].code, such as VALIDATION_ERROR or SESSION_EMPTY.
application/problem+json A problem document: type, title, status, detail and instance, with no messages key. type, compared as the whole URI.

A 400 and a 409 can arrive in either shape. A 401, 403, 404 or 500 from the service is always a problem document. These are the problem types the Session and Workflow APIs return:

type Status Meaning
about:blank 400, 401, 403, 404, 500 The status alone describes the problem: a body that could not be read as the request, no credential at all, a denial before the operation ran, a path this API doesn’t serve, or an unhandled failure.
https://pointservices.com/problems/invalid-token 401 A token was sent and refused. Get a fresh one.
https://pointservices.com/problems/not-authorized 403 You are signed in, and you may not act on this resource or product.
https://pointservices.com/problems/not-found 404 The identifier you sent did not resolve.
https://pointservices.com/problems/invalid-request 400 The Content-Type header names a character set the service can’t use.
https://pointservices.com/problems/concurrent-modification 409 Another request changed the same resource first, and nothing from yours was applied. Read it again before you resubmit.

The rules that follow from this:

  1. Branch on the Content-Type first, then on messages[].code or type. Compare the media type only, ignoring parameters such as charset. Check that messages exists before you read messages[0].code: on several endpoints the problem document is the common case, not the exception.
  2. Some rejections carry no JSON body at all. The edge in front of the service refuses a POST without Content-Type, or a value that looks like SQL or markup, with a 403 and an HTML body, and a rate-limited request with a bare 429. Write your client to tolerate an error it can’t parse.
  3. Treat an unrecognized message code as non-retryable. The vocabulary is closed but additive; meeting a new code means stop, not retry.
  4. What a 500 means depends on the call. On the reads it means nothing happened, so read again. On Start a Session and Stage Data the 500 is not stored, so send the same request again with the same Idempotency-Key: if the failed attempt’s work was kept you get its original response, and if not it runs again, so you end up with one session or one snapshot either way. On Start a Workflow, Start a Workflow in a Session and Reconfirm a Workflow, the outcome is unknown, not that nothing happened. With an Idempotency-Key, a 500 on those three is stored and every retry under that key returns it, so re-read, or search by correlationId, then send the call under a new key only if it didn’t happen. Without a key, retrying blind is how one workflow becomes two. On Edit a Workflow, send the same request again: a repeated outcome report is recorded again and changes no answer.
  5. Send an Idempotency-Key on every POST you might retry, except Edit a Workflow, which takes none. A retry under the same key returns the first response instead of doing the work again. See Retrying Safely.
  6. Quote instance when you report an error. It is written urn:pps:request:<id>, and the id is the same one the x-pps-request-id response header carries. It is what lets PPS find that one request.

Things to know

  • A session never expires, and it is not a login session. Holding a sessionId is not permission to use it: every call is authorized on its own.
  • dataStaged never returns to false once a stage has succeeded. Re-staging replaces the snapshot; nothing empties a session.
  • A 409 SESSION_EMPTY means stage first. It is the one 409 you can fix on your own: stage data, then start the workflow again.
  • A rejected stage changes nothing. The previous snapshot stays current, and no partial one is recorded.
  • status is one of four lowercase values: processing, complete, failed and cancelled. Branch on it, not on message codes.
  • A request’s correlationId is limited to 255 characters, after trimming. On a session start, a workflow start (direct or in a session) or a reconfirm, a longer value is a 400 and nothing is stored. A term’s own correlationId has the same limit, but a longer one is ignored rather than rejected; see Correlation ids on terms.
  • Find Workflows returns at most 100 workflows, newest first, with no paging, and it reads at most the newest 1,000 matching runs. Make your correlation ids distinctive.
  • A reconfirm body decides what runs. No body, or {}, re-runs against the session’s current data. A body with terms records a new snapshot of the session, stated in full, and re-runs against it.
  • Every POST needs Content-Type: application/json, including a session start or a reconfirm with no body.

Copyright © Pitchpoint Solutions. All rights reserved.