# Read a Session

Source: https://docs.pitchpointsolutions.com/api/session/get_session/

**Beta**

Returns the current state of one session. It changes nothing: reading a session never stages data, never starts a workflow, and never affects a workflow already running.

There is exactly one question this answers: **has anything been staged into this session yet.** It tells you nothing about the progress of any workflow you have started — workflow state lives behind the workflow handle, on [Read a Workflow](https://docs.pitchpointsolutions.com/api/workflow/get_workflow/).

> **Before Starting:** Get the URL to submit against from your Pitchpoint Account Representative.

### Sample

```bash
url="https://api.pointservices.com/riskinsight-services-ws/resources/v1/sessions/0000000000013500001"
curl -X GET "${url}" \
  -H "Authorization: Bearer your_access_token_here" \
  -H "Accept: application/json"
```

#### Header Properties

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

This call sends no body, so `Content-Type` is not required. Sending it anyway costs nothing and is the safer habit: on the POST calls edge protection in deployed environments refuses a request that omits it, with a `403` carrying an HTML body rather than any response documented here.

`Accept` is not enforced &mdash; a request without it is answered normally with JSON &mdash; 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](https://docs.pitchpointsolutions.com/api/workflow/list_workflows/); setting the header globally in your HTTP client does not make your orders findable.

See the [Common Headers guide](https://docs.pitchpointsolutions.com/developer_guides/headers/index/) for details on the optional `X-PPS-*` headers above.

#### Path Parameters

| Property  | Description                                                                                                     | Type   |
|-----------|-------------------------------------------------------------------------------------------------------------------|--------|
| sessionId | (mandatory) The identifier returned when the session was started. Treat it as opaque: store and echo it, never parse it. | string |

> **Warning:** **This response never carries the staged data itself.** It has no `terms` field, whether or not anything has been staged &mdash; `dataStaged` tells you *that* a snapshot exists, never *what* is in it. This call answers one question only. To see what the session holds, use [Read the Staged Data](https://docs.pitchpointsolutions.com/api/session/read_session_sami/).

### Responses

> **Warning:** **Not every response carries the same body. Branch on the `Content-Type` first, and then on what the body contains.** `application/json` is the `messages` envelope described on this page: read `messages[].code`. `application/problem+json` is a problem document, with `type`, `title`, `status`, `detail` and `instance` and no `messages` key: read `type`, and compare it as the whole URI (for example `https://pointservices.com/problems/concurrent-modification`). Some rejections 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. See [Error handling](https://docs.pitchpointsolutions.com/developer_guides/sessions_and_workflows/error_handling/) for the whole rule.

**200**

The session's current state. `messages` is present but empty &mdash; a plain read produces no message.

| Property | Description                                                                          | Type   |
|----------|------------------------------------------------------------------------------------------|--------|
| session  | (present) The session. Same shape as on [Start a Session](https://docs.pitchpointsolutions.com/api/session/start_session/). | object |
| messages | (present) Always an array, never null. Empty on a successful read.                     | array  |

| Property      | Description                                                                                                                                | Type    |
|---------------|------------------------------------------------------------------------------------------------------------------------------------------|---------|
| sessionId     | (present) Echoes the identifier you called with.                                                                                           | string  |
| dataStaged    | (present) `false` until the first successful stage, `true` from then on. **It never returns to `false`** &mdash; re-staging replaces the snapshot, and nothing empties a session that has held data. | boolean |
| correlationId | (present) Your value when the session was started with one, otherwise the value this service generated.                                    | string  |

Example:
```json
{
  "session": {
    "sessionId": "0000000000013500001",
    "dataStaged": true,
    "correlationId": "alpha_numeric_string_to_help_identify_this_session"
  },
  "messages": []
}
```

**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:
```json
{
  "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.

The `invalid-token` type deliberately does not say why the token was refused: the platform cannot tell an expired token from a revoked, badly signed or malformed one. Treat every `invalid-token` the same way.

> **Warning:** **Refresh your token on a 401, and only on a 401.** An expiring token moves a call from 200 to 401, never to 403. Obtain a fresh access token and retry the request once. If it fails again, stop and surface the error rather than looping &mdash; 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 read this session. Holding a `sessionId` is not permission to use it &mdash; every call is authorized independently, so do not treat the value as a secret or as proof of anything.

A 403 is an **authorization decision**: your identity was established and the answer is still no. It is never a statement about your token, so refreshing the token will not turn it into a 200. A refused request leaves nothing behind, so there is nothing to clean up.

The body is a problem document (`application/problem+json`), not the `messages` envelope, so there is no `code` to branch on. Its `type` is one of two values:

| `type` | Meaning |
|--------|---------|
| `about:blank` | The request was denied before the operation itself ran. |
| `https://pointservices.com/problems/not-authorized` | A policy decision about the specific resource or product you named. |

Example:
```json
{
  "type": "https://pointservices.com/problems/not-authorized",
  "title": "Not authorized",
  "status": 403,
  "detail": "The authenticated identity is not permitted to perform this action.",
  "instance": "urn:pps:request:0000000000000000000000000000000000000000000000000000"
}
```

> **Warning:** **A 403 can also come from the edge, before this service is reached,** when a request omits `Content-Type` or carries a value resembling SQL injection or cross-site scripting. That refusal carries an HTML body, not a problem document, and this service never sees it. Check the `Content-Type` of the response before you parse it. A value that legitimately contains such text should be encoded &mdash; Base64, for instance &mdash; rather than sent raw.

**404**

No session exists with this identifier, or the path you called is not served.

When this API answers, the body is a problem document (`application/problem+json`) in both cases, and its `type` tells them apart.

**`https://pointservices.com/problems/not-found`** means the identifier you sent did not resolve.

| Property | Description                                                                              | Type   |
|----------|--------------------------------------------------------------------------------------------|--------|
| type     | (present) `https://pointservices.com/problems/not-found` here. Compare it as the whole URI. | string |
| title    | (present) Short human-readable summary.                                                   | string |
| status   | (present) Repeats the HTTP status code.                                                   | number |
| detail   | (present) Human-readable explanation naming what was not found. Never machine-parsed.     | string |
| instance | (present) An identifier for this one request. Quote it when contacting support.           | string |

Example:
```json
{
  "type": "https://pointservices.com/problems/not-found",
  "title": "No such resource",
  "status": 404,
  "detail": "Session[0000000000013500001] not found",
  "instance": "urn:pps:request:0000000000000000000000000000000000000000000000000000"
}
```

Treat this as a single outcome: nothing in the body narrows down why the identifier did not resolve. Check the identifier you sent, and the tenancy of the credential you sent it with. An identifier this API has already issued to you is readable the moment you receive it, so a 404 on one is final rather than a race. Retrying will not make it appear.

**`about:blank`** means the path itself is not served here, so the request never reached this operation: a wrong host, or an environment where this API is not deployed.

A URL missing the `/riskinsight-services-ws/resources/v1` path prefix does not reach this API at all. The 404 then comes from infrastructure in front of it, and carries no body this API defines, so don't try to parse it. If a 404 has no problem document, check the path prefix 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. Because the edge sends this response before the request reaches the service, it is not described in the OpenAPI specifications or the API Explorer.

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 is a problem document (`application/problem+json`) with `type` `about:blank`, not the `messages` envelope, so branch on the status alone. When you report the error to PPS, quote the document's `instance`: it carries the same id as the `x-pps-request-id` response header, and it is what lets PPS find this exact request.

**Retrying this call is safe.** This call changes nothing, so it is always safe to read again.
