---
title: "Background processing - Signature sessions"
description: "How to turn on background processing in Rest PKI Core signature sessions so users are redirected to your app without waiting for document processing."
canonical: "https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/signature-sessions/background-processing"
locale: "en"
product: "Rest PKI Core"
last_updated: "2026-10-12"
---

# Background processing - Signature sessions

By default, users are kept waiting while documents are processed before being redirected back to your application. If you want to provide your users with a faster
experience, turn on background processing by passing `EnableBackgroundProcessing = true` upon creation of the session.

On .NET:

```cs
var response = await restPkiService.CreateSignatureSessionAsync(new CreateSignatureSessionRequest() {
	...
	EnableBackgroundProcessing = true,
});
return Redirect(response.RedirectUrl);
```

On PHP:

```php
$request = new CreateSignatureSessionRequest();
$request->enableBackgroundProcessing = true;

$response = $service->createSignatureSession($request);

header("Location: {$response->redirectUrl}");
```

On Java:

```java
CreateSignatureSessionRequest request = new CreateSignatureSessionRequest();
request.setEnableBackgroundProcessing(true);

CreateSignatureSessionResponse response = restPkiService.createSignatureSession(request);

return "redirect:" + response.getRedirectUrl();
```

Direct API integration:

```plaintext
POST {endpoint}/api/signature-sessions
{
	...
	"enableBackgroundProcessing": true
}
```

In this case, users do not wait for documents to be processed. However, your callback implementation must be ready to handle the case of a signature session whose
documents are not yet available for download.

> **Note**
>
> No changes are needed to your app if you opt for the [Webhook flow](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/signature-sessions#webhook-flow), since in this case there's no callback handling

## Aditional statuses

In addition to the possible statuses `Completed` and `UserCancelled`, two additional statuses are possible when the user is redirected on your app: `Processing` and `ProcessingError`.

While a session is still `Processing`, some documents will be in status `Processing` and cannot be downloaded. Only when the session transitions to the `Completed`
status are all documents ready to be downloaded.

> **Note**
>
> The status `ProcessingError` is a rare condition that occurrs only in corner cases such as the user's certificate being revoked during the time between the
> start of the session and the completion of the background processing. It is perfectly appropriate for your app to `throw` if this status is returned.

## Adapting callback

Let's change our callback implementation to deal with this.

On .NET:

```cs
public class SessionCallbackController : Controller {
	...	
	public async Task<IActionResult> Index(Guid signatureSessionId) {
		var session = await restPkiService.GetSignatureSessionAsync(signatureSessionId);
		if (session.Status != SignatureSessionStatus.Completed && session.Status != SignatureSessionStatus.Processing) {
			return Redirect("/");
		}
		return View(session);
	}
}
```

On PHP:

```php
$sessionId = $_GET['signatureSessionId'];

$session = $service->getSignatureSession($sessionId);
if ($session->status != SignatureSessionStatus::COMPLETED && $session->status != SignatureSessionStatus::PROCESSING) {
	header("Location: http://localhost:8000/");
	exit;
}
```

On Java:

```java
@Controller
public class SessionCallbackController {
	...
	public String index(
		Model model, 
		@RequestParam(value="signatureSessionId") String sessionId
	) throws Exception {
		SignatureSession session = restPkiService.getSignatureSession(UUID.fromString(sessionId));
		if (session.getStatus() != SignatureSessionStatus.COMPLETED &&
			session.getStatus() != SignatureSessionStatus.PROCESSING) {
			return "redirect:/";
		}
		// The link to each signed file comes from the document's DocumentModel, once the document is completed
		Map<UUID, String> signedFileUrls = new HashMap<>();
		for (SignatureSessionDocument document : session.getDocuments()) {
			if (document.getStatus() == DocumentStatus.COMPLETED) {
				signedFileUrls.put(document.getId(), restPkiService.getDocumentModel(document.getId()).getSignedFile().getUrl());
			}
		}
		model.addAttribute("session", session);
		model.addAttribute("signedFileUrls", signedFileUrls);
		return "signature-callback/index";
	}
}
```

Notice that now we also consider the status `Processing` to be normal. Now, let's change the view:

On .NET, the Razor view would be:

```html
@using Lacuna.RestPki.Api
@using Lacuna.RestPki.Client
@model SignatureSession
<h2>Signed documents</h2>
<ul>
	@foreach (var document in Model.Documents)
	{
		<li>
			@if (document.Status == DocumentStatus.Completed)
			{
				<a href="@document.SignedFile.Url">@document.SignedFile.Name</a>
			}
			else
			{
				@document.OriginalFile.Name
				<text> (processing)</text>
			}
		</li>
	}
</ul>
```

On PHP, the client side view would be:

```php
<h2>Signed documents</h2>
<ul>
	<?php for ($i = 0; $i < count($session->documents); $i++) { 
		$document = $session->documents[$i]; ?>

		<li>
			<?php if ($document->status == DocumentStatus::COMPLETED) { ?>
				<a href="<?= $document->signedFile->location ?>"><?= $document->signedFile->name ?></a>
			<?php } else { ?>
				<?= $document->originalFile->name ?>
				<text> (processing)</text>
			<?php } ?>
		</li>
	<?php } ?>
</ul>
```

On Java, the Thymeleaf view would be:

```html
<h2>Signed documents</h2>
<ul>
	<li th:each="document : ${session.getDocuments()}">
		<a th:if="${signedFileUrls.containsKey(document.getId())}" th:href="${signedFileUrls.get(document.getId())}">
			<span th:text="${document.getSignedFile().getName()}"/>
		</a>
		<span th:unless="${signedFileUrls.containsKey(document.getId())}">
			<span th:text="${document.getOriginalFile().getName()}"/> (processing)
		</span>
	</li>
</ul>
```

Notice how we render each list item differently based on each document's status. The PHP client exposes the link to the signed file only as `location`,
a deprecated name for `url` (see [Implementing the callback handler](https://docs.lacunasoftware.com/en-us/articles/rest-pki/core/integration/signature-sessions#implementing-the-callback-handler)).
