API REFERENCE

Beta

Start a Session

Starts an empty session and returns its identifier. A session is a workspace that holds one set of data: you stage that data into it, then start one or more workflows against it.

This is the only way to obtain a sessionId. The value is issued by this service and is never derived, guessed or constructed by a client.

Get the URL to submit against from your Pitchpoint Account Representative, along with the products your account is entitled to use.

Sample

url="https://api.pointservices.com/riskinsight-services-ws/resources/v1/sessions"
curl -X POST "${url}" \
  -H "Authorization: Bearer your_access_token_here" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "correlationId": "alpha_numeric_string_to_help_identify_this_session"
  }'

Send Content-Type: application/json even when you send no body. The request body here is optional, and a client built to send nothing at all will often drop the header along with it. In deployed environments edge protection refuses a request that omits the header, answering 403 with an HTML body — not any response documented on this page, and not something this service can explain, because it never sees the request. A local or unprotected deployment may accept the same call, so test against a deployed environment before assuming the header is optional.

Header Properties

Property Value Required?
Authorization Bearer your token true
Content-Type application/json true
Accept application/json false
X-PPS-UserAlias your value false
X-PPS-UserAgent your value false
X-PPS-CorrelationID your value false

Send Content-Type: application/json on every POST, including one with no body at all. In deployed environments a request that arrives without it is refused by edge protection in front of the application, with a 403 carrying an HTML body rather than any response documented here — and because the service never sees the request, nothing can explain it to you. A local or unprotected deployment may accept the same request, so do not take a working call there as evidence the header is optional.

Accept is not enforced — a request without it is answered normally with JSON — but send it anyway, so that a future change to content negotiation cannot alter what you receive.

X-PPS-CorrelationID is a support-tracing header and is not the same thing as the correlationId field in a request body. Only the body field is recorded against an order and searched by Find Workflows; setting the header globally in your HTTP client does not make your orders findable.

See the Common Headers guide for details on the optional X-PPS-* headers above.

Request Data Properties

The body is optional. An absent body, an empty body and {} all mean the same thing, and all start a session with a correlation id this service generates for you.

Property Description Type
correlationId (optional) Your own reference for this session, at most 255 characters. It is not required to be unique. Leading and trailing whitespace is trimmed and a blank value is treated as absent. Longer than 255 characters is rejected. string

This session’s correlationId is not inherited by the workflows you later start against it, and it is not searchable. It describes the session only. Find Workflows searches the correlation ids supplied when starting a workflow, never this one. To find a workflow later, supply a correlationId when you start it itself.

A value that resembles SQL or HTML is refused at the edge with no explanation, so encode such values — Base64, for instance — rather than sending them raw.

Responses

Not every response carries the same body, so branch on the status code first, and then on what the body actually contains. Some responses carry the messages envelope described on this page; others carry a JSON problem document with an entirely different set of fields; others carry no JSON at all. A client that calls its JSON parser on every non-2xx body, or that reads messages[0].code without first checking that messages is present, will fail on the responses it is most likely to meet.

201

The session exists and is ready to stage data into. loanStaged is always false here.

Property Description Type
session (present) The session that was started. See section below. object
messages (present) Always an array, never null. Carries one message whose code is SESSION_STARTED. array
session
Property Description Type
sessionId (present) The identifier for this session, used in the path of every later call against it. Treat it as opaque: store and echo it, never parse it. string
loanStaged (present) Whether anything has been staged. Always false on a newly started session. Once it becomes true it never returns to false. boolean
correlationId (present) Your value when you supplied one, otherwise a value this service generated for the session. string
links (present) Where to go next. See section below. object
Property Description Type
self (present) Re-reads this session. GET. object
sami (present) Stages SAMI terms into this session. Carries method POST. object
workflows (present) Starts a workflow against this session. Carries method POST. object

Each link is an object carrying an href, plus a method when the verb is not GET. workflows is published even before anything is staged, because the links describe what this API offers rather than what will succeed right now.

Example:

{
  "session": {
    "sessionId": "0000000000013500001",
    "loanStaged": false,
    "correlationId": "alpha_numeric_string_to_help_identify_this_session",
    "links": {
      "self": {
        "href": "https://api.pointservices.com/riskinsight-services-ws/resources/v1/sessions/0000000000013500001"
      },
      "sami": {
        "href": "https://api.pointservices.com/riskinsight-services-ws/resources/v1/sessions/0000000000013500001/sami",
        "method": "POST"
      },
      "workflows": {
        "href": "https://api.pointservices.com/riskinsight-services-ws/resources/v1/sessions/0000000000013500001/workflows",
        "method": "POST"
      }
    }
  },
  "messages": [
    {
      "code": "SESSION_STARTED",
      "text": "session started",
      "timestamp": "2026-08-07T15:01:42Z"
    }
  ]
}

Starting a session is not idempotent. Each call starts a new one, so a client that retries after a timeout will hold two sessions rather than recovering the first. A session that is never staged into is inert and costs nothing, but a client should not start more sessions than it stages loans into. Nothing is billed until you start a workflow.

400

The request was refused. The two causes return different body shapes, and on this endpoint the problem-document shape is the one you will meet most often:

Cause Body
correlationId longer than 255 characters the messages envelope, VALIDATION_ERROR
A body that is not a JSON object — an array, a bare value, or malformed JSON a JSON problem document, no messages key
A field of the wrong type a JSON problem document, no messages key

Only the correlationId length is a value this endpoint evaluates. Everything else fails before evaluation, so a client that reads messages[0].code on every 400 breaks on the majority of them here.

An unrecognized field is currently accepted and ignored rather than rejected. A body carrying a field this endpoint does not define starts the session normally and returns 201, so a typo or a stale field name will not be reported back to you. Do not rely on this endpoint to catch one, and do not rely on the leniency either — send only the field documented above.

A 400 arrives in two different body shapes, decided by how far the request got before it was refused. Check for a messages array first, and fall back to the problem document when it is absent.

A value this service evaluated and rejected carries the messages envelope with the code VALIDATION_ERROR.

Property Description Type
messages (present) Always an array, never null. Carries one message whose code is VALIDATION_ERROR. array
messages[].code (present) Always VALIDATION_ERROR on this shape. string
messages[].text (present) Human-readable description of what was wrong. Never machine-parsed — the wording is not contractual. string
messages[].timestamp (present) RFC 3339 UTC with a trailing Z. Fractional seconds appear only when they are not zero, so parse this value rather than slicing it. string

Example:

{
  "messages": [
    {
      "code": "VALIDATION_ERROR",
      "text": "A session start request's correlationId must be at most 255 characters",
      "timestamp": "2026-08-07T15:01:42Z"
    }
  ]
}

A body that could not be read as this request at all — a JSON array where an object was expected, a field of the wrong type, or malformed JSON — is refused before the service evaluates any value, so there is nothing to put in a messages array. It carries a JSON problem document instead, with Content-Type: application/problem+json and no messages key and no VALIDATION_ERROR code.

Example:

{
  "type": "about:blank",
  "title": "Bad Request",
  "status": 400,
  "detail": "Request body has a field that must be a value of type SessionStartRequest",
  "instance": "urn:pps:request:0000000000000000000000000000000000000000000000000000"
}

A client that reads messages[0].code on every 400 without checking that messages exists will throw on this second shape. Branch on the presence of messages, not on the status.

No session is started, and no session object accompanies either shape.

401

No credential the platform could accept reached the service.

The body is a JSON problem document, not the messages envelope, and the response carries a WWW-Authenticate: Bearer realm="Helix" challenge. Read the machine-readable part from type; title and detail are human copy and are not contractual.

Property Description Type
type (present) An absolute URI identifying the problem. about:blank when no credential was sent at all. string
title (present) Short human-readable summary. string
status (present) Repeats the HTTP status code. number
detail (present) Human-readable explanation. Never machine-parsed. string
instance (present) An identifier for this one request. Quote it when contacting support. string

Examples:

{
  "type": "about:blank",
  "title": "Unauthorized",
  "status": 401,
  "detail": "Authentication is required. Present a bearer access token in the Authorization header.",
  "instance": "urn:pps:request:0000000000000000000000000000000000000000000000000000"
}

{
  "type": "https://pointservices.com/problems/invalid-token",
  "title": "The access token was not accepted",
  "status": 401,
  "detail": "The access token was rejected.",
  "instance": "urn:pps:request:0000000000000000000000000000000000000000000000000000"
}

The second form carries WWW-Authenticate: Bearer realm="Helix", error="invalid_token", and is what a token the service will not accept returns.

Treat a 401 and a 403 alike: both mean your credential did not work, and neither distinguishes reliably enough to build separate recovery paths on. Obtain a fresh access token and retry the request once. If it fails again, stop and surface the error rather than looping — repeated attempts with a credential the service has already refused will meet the rate throttle described below.

403

Your credential was understood but you are not permitted to start a session on this account. No session is started.

The body does not carry the messages envelope, so there is no code to branch on. Branch on the status alone, and treat the body as opaque: do not assume it is empty, and do not assume it is JSON.

A 403 is not always a permissions problem — try a fresh token first. A credential the service will not honour can be refused with either status, so a sudden wall of 403s on calls that worked a moment ago is more often an expired token than a change to your entitlements. Obtain a new access token and retry once. If it fails again, then treat it as entitlement and talk to your Account Representative.

A 403 is also produced at the edge, before this service is reached, when a request omits Content-Type or carries a value resembling SQL injection or cross-site scripting. Those refusals carry an HTML body and this service never sees them. A value that legitimately contains such text should be encoded — Base64, for instance — rather than sent raw.

404

The path you called is not served. Check that the URL carries the riskinsight-services-ws context root — without it every path on this API answers 404, with the empty body described below.

This path takes no resource identifier, so a 404 here means the path itself is not served — most often a URL missing the riskinsight-services-ws context root. The refusal is produced by infrastructure in front of the application, which never sees the request. It carries no body this API defines, so branch on the status alone and do not attempt to parse what comes back. Its exact shape depends on the environment you are calling.

If a 404 has no body, check the context root before anything else.

429

Refused by a rate throttle at the edge, before this service is reached. The throttle counts requests per source address across every endpoint on both the session and workflow surfaces.

The refusal carries no body, no messages array and no Retry-After header, and this service never sees it, so it will not appear in any support trace.

Back off and resume. When following a workflow to completion, an interval that stays clear of the throttle is two seconds for the first two checks, then five, then ten seconds thereafter, with an overall deadline after which you stop and investigate.

500

An unhandled failure inside the service. The body does not carry the messages envelope, so branch on the status alone.

A 500 means the outcome is unknown, not that nothing happened. A failure raised after a write has already committed leaves that write in place. A session may or may not have been started, and you hold no identifier for it either way. Start a new session rather than retrying this one. Retrying blind is how one order becomes two, and nothing on this surface removes a duplicate for you.


Copyright © Pitchpoint Solutions. All rights reserved.