# Signed In-App Purchase History

OnsideKit can produce a **signed** in-app purchase history as a compact JWS (JSON Web Signature) for the current user. Send it (or the order IDs it contains) to your backend to validate purchases — see [Backend Validation & Merchant API](/sdk/purchase-validation/merchant-api.md).

## Create the request

```swift
@MainActor static func makeSignedInAppsHistoryRequest()
    -> Result<OnsideSignedInAppsHistoryRequest, OnsideSignedInAppsHistoryRequestError>
```

The call returns a request object on success, or a pre-flight error:

```swift
switch Onside.makeSignedInAppsHistoryRequest() {
case .success(let request):
    request.delegate = self
    self.historyRequest = request   // retain it
    request.start()

case .failure(let error):
    // .notLoggedIn or .notSupportedInLocalTesting (pre-flight),
    // or a network error.
    print("Couldn't create history request: \(error)")
}
```

{% hint style="info" %}
This API requires an authenticated user — it returns `.notLoggedIn` if there is no session (it does **not** trigger login). In [local-testing](/sdk/advanced-and-tooling/local-testing.md) mode it returns `.notSupportedInLocalTesting`.
{% endhint %}

## The request object

```swift
protocol OnsideSignedInAppsHistoryRequest: AnyObject {
    @MainActor var delegate: OnsideSignedInAppsHistoryRequestDelegate? { get set }
    @MainActor func start()
    @MainActor func stop()
}
```

Retain the request for the whole operation (a dropped reference is cancelled). Use `stop()` to cancel.

## Handle the result

```swift
extension MyValidator: OnsideSignedInAppsHistoryRequestDelegate {

    func onsideSignedInAppsHistoryRequest(
        _ request: OnsideSignedInAppsHistoryRequest,
        didReceive response: OnsideSignedInAppsHistory
    ) {
        // response.data is the raw JWS blob; response.string is its UTF-8 form.
        sendToBackend(response.data)
    }

    func onsideSignedInAppsHistoryRequest(
        _ request: OnsideSignedInAppsHistoryRequest,
        didFailWithError error: OnsideSignedInAppsHistoryRequestError
    ) {
        print("History request failed: \(error)")
    }

    // Optional — always called after success or failure.
    func onsideSignedInAppsHistoryRequestDidFinish(
        _ request: OnsideSignedInAppsHistoryRequest
    ) {
        self.historyRequest = nil
    }
}
```

### The history value

```swift
struct OnsideSignedInAppsHistory {
    var data: Data        // the raw JWS blob
    var string: String?   // a UTF-8 decoding of `data`, when valid
}
```

`string` is a convenience that UTF-8-decodes `data`; the JWS is normally a printable string, so it is usually non-`nil`.

## Errors

`OnsideSignedInAppsHistoryRequestError`:

<table><thead><tr><th width="280">Case</th><th>Cause</th></tr></thead><tbody><tr><td><code>.notLoggedIn</code></td><td>No authenticated user (this API does not trigger login).</td></tr><tr><td><code>.notSupportedInLocalTesting</code></td><td>Running with a <code>.storekit</code> local-testing configuration.</td></tr><tr><td><code>.connectionError</code></td><td>Network failure.</td></tr><tr><td><code>.serviceUnavailable</code></td><td>Server returned 5xx.</td></tr><tr><td><code>.appNotRegistered</code></td><td>The app/install isn't recognized by Onside (HTTP 404).</td></tr><tr><td><code>.cancelled</code></td><td>The request was cancelled.</td></tr><tr><td><code>.internalError</code></td><td>Parsing or other unexpected error.</td></tr></tbody></table>

Once your backend has the signed history (or the order IDs from it), continue with [Backend Validation & Merchant API](/sdk/purchase-validation/merchant-api.md).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.onside.io/sdk/purchase-validation/signed-in-apps-history.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
