API Samples & Common Scenarios
This page demonstrates common integration scenarios with the Platina Standard REST API. All examples use API version v8.0 and assume OAuth 2.0 authentication.
π‘ Tip: The API exposes interactive documentation at
/swaggerwhere you can try endpoints directly. See Swagger UI.
Authentication
All requests require a Bearer token in the Authorization header. See the Authorization Guide for setup.
Get a token (C#)
using Microsoft.Identity.Client;
var app = ConfidentialClientApplicationBuilder
.Create("<client-id>")
.WithClientSecret("<client-secret>")
.WithAuthority("https://login.microsoftonline.com/<tenant-id>/")
.Build();
var result = await app.AcquireTokenForClient(
new[] { "api://<client-id>/.default" }
).ExecuteAsync();
string accessToken = result.AccessToken;
Using the token
All subsequent examples use this helper:
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
var client = new HttpClient
{
BaseAddress = new Uri("https://your-server/api/v8.0/")
};
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
cURL
TOKEN="<your-bearer-token>"
BASE_URL="https://your-server/api/v8.0"
curl -H "Authorization: Bearer $TOKEN" "$BASE_URL/diaries"
Scenario 1 β List Diaries and Reference Data
Before creating cases or deeds, you need to discover available diaries, case types, and other reference data.
List all diaries
GET /v8.0/diaries
var response = await client.GetAsync("diaries");
var diaries = await response.Content.ReadFromJsonAsync<JsonElement>();
// Each diary has an "id" (ApiId) and "name"
foreach (var diary in diaries.GetProperty("items").EnumerateArray())
{
Console.WriteLine($"{diary.GetProperty("id")} β {diary.GetProperty("name")}");
}
List reference data
GET /v8.0/reference-data
This returns links to all available reference data collections:
var refData = await client.GetFromJsonAsync<JsonElement>("reference-data");
// Returns links to: countries, case-types, deed-types, business-codes,
// journalized-case-statuses, secrecy-levels, pul-levels, etc.
Useful reference data endpoints
| Endpoint | Returns |
|---|---|
GET /reference-data/case-types |
All case types |
GET /reference-data/deed-types |
All deed types |
GET /reference-data/business-codes |
Business codes |
GET /reference-data/journalized-case-statuses |
Case statuses |
GET /reference-data/journalized-case-origins |
Case origins (Incoming, Outgoing, etc.) |
GET /reference-data/confidential-paragraphs |
Confidentiality paragraphs |
GET /diaries/{id}/handling-officers |
Handling officers for a diary |
GET /diaries/{id}/postlists |
Post lists for a diary |
GET /diaries/{id}/case-types |
Case types available in a specific diary |
Scenario 2 β Create a Journalized Case
Register a new incoming case in a diary.
POST /v8.0/diaries/{diaryId}/journalized-cases
Content-Type: application/json
Request body
{
"registrationDate": "2025-04-01T00:00:00+02:00",
"inOutDate": "2025-04-01T00:00:00+02:00",
"statusId": "<status-api-id>",
"origin": "Incoming",
"caseTypeId": "<case-type-api-id>",
"pulLevel": 0,
"secrecyLevel": 0,
"title": "Building permit application β Storgatan 12",
"description": "Application for building permit, residential extension.",
"initiators": [
{
"name": "Anna Andersson",
"city": "Stockholm",
"zipCode": "114 32",
"streetAddress": "Storgatan 12",
"email": "anna.andersson@example.com",
"personOrgNumber": "198501011234"
}
],
"handlingOfficers": [
{
"id": "<officer-api-id>",
"message": "Please review and register",
"isMain": true
}
]
}
C# example
var diaryId = "Nk981MWbd04"; // from GET /diaries
var caseData = new
{
registrationDate = "2025-04-01T00:00:00+02:00",
inOutDate = "2025-04-01T00:00:00+02:00",
statusId = "<status-api-id>",
origin = "Incoming",
caseTypeId = "<case-type-api-id>",
pulLevel = 0,
secrecyLevel = 0,
title = "Building permit application β Storgatan 12",
description = "Application for building permit, residential extension.",
initiators = new[]
{
new
{
name = "Anna Andersson",
city = "Stockholm",
zipCode = "114 32",
streetAddress = "Storgatan 12",
email = "anna.andersson@example.com"
}
}
};
var json = JsonSerializer.Serialize(caseData);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync($"diaries/{diaryId}/journalized-cases", content);
if (response.StatusCode == System.Net.HttpStatusCode.Created)
{
// The Location header contains the URL to the new case
var location = response.Headers.Location;
// The X-Platina-DiaryNumber header contains the assigned diary number
var diaryNumber = response.Headers.GetValues("X-Platina-DiaryNumber").First();
Console.WriteLine($"Case created! Diary number: {diaryNumber}");
Console.WriteLine($"Location: {location}");
}
Response
- 201 Created β Case was created. Check
Locationheader for the case URL andX-Platina-DiaryNumberfor the assigned number. - 400 Bad Request β Validation error (missing required fields, invalid data).
- 404 Not Found β Diary not found or no access.
- 409 Conflict β Configuration conflict (e.g. business code required but not provided).
Scenario 3 β Create a Deed
Register a standalone deed (not linked to a journalized case).
POST /v8.0/deeds
Content-Type: application/json
{
"diaryId": "<diary-api-id>",
"postListId": "<postlist-api-id>",
"registrationDate": "2025-04-01T00:00:00+02:00",
"inOutDate": "2025-04-01T00:00:00+02:00",
"origin": "DrawnUp",
"deedTypeId": "<deed-type-api-id>",
"pulLevel": 0,
"secrecyLevel": 0,
"title": "Internal memo β Budget 2025",
"description": "Departmental budget proposal for fiscal year 2025.",
"initiators": [
{
"name": "Erik Eriksson",
"email": "erik.eriksson@example.com"
}
]
}
Response
- 201 Created β Deed created.
Locationheader has the deed URL.
Scenario 4 β Create a Deed Under a Journalized Case
Add a deed to an existing case. This is the most common pattern: a case is created first, then deeds are added as the case progresses.
POST /v8.0/journalized-cases/{caseId}/deeds
Content-Type: application/json
{
"postListId": "<postlist-api-id>",
"registrationDate": "2025-04-01T00:00:00+02:00",
"inOutDate": "2025-04-01T00:00:00+02:00",
"origin": "Incoming",
"deedTypeId": "<deed-type-api-id>",
"pulLevel": 0,
"secrecyLevel": 0,
"title": "Architect drawings β revision 2",
"description": "Updated floor plans received from architect."
}
Response
- 201 Created β
Locationheader has the deed URL,X-Platina-DiaryNumberhas the assigned number.
Scenario 5 β Upload a Document to a Case
Attach a file (e.g. PDF, DOCX) to a journalized case.
POST /v8.0/journalized-cases/{caseId}/documents/from-file
Content-Type: multipart/form-data
C# example
var caseId = "ozA5b1LlEzx";
var filePath = @"C:\Documents\building-plans.pdf";
using var fileStream = File.OpenRead(filePath);
using var formContent = new MultipartFormDataContent();
var fileContent = new StreamContent(fileStream);
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "file",
FileName = Path.GetFileName(filePath)
};
formContent.Add(fileContent);
var response = await client.PostAsync(
$"journalized-cases/{caseId}/documents/from-file",
formContent
);
if (response.StatusCode == System.Net.HttpStatusCode.Created)
{
var documentUrl = response.Headers.Location;
Console.WriteLine($"Document uploaded: {documentUrl}");
}
cURL example
curl -X POST "$BASE_URL/journalized-cases/$CASE_ID/documents/from-file" \
-H "Authorization: Bearer $TOKEN" \
-F "file=@building-plans.pdf"
Scenario 6 β Search and Retrieve Cases
Look up a case by diary number
GET /v8.0/journalized-cases/with-diary-number/{diaryNumber}
var diaryNumber = "2025-0042";
var response = await client.GetAsync(
$"journalized-cases/with-diary-number/{diaryNumber}"
);
var caseData = await response.Content.ReadFromJsonAsync<JsonElement>();
Search cases with filters
GET /v8.0/journalized-cases/with-metadata?diaryId={id}&initiatorName={name}
Get a case with its deeds
// Get the case
var caseResponse = await client.GetAsync($"journalized-cases/{caseId}");
var caseData = await caseResponse.Content.ReadFromJsonAsync<JsonElement>();
// Get its deeds
var deedsResponse = await client.GetAsync($"journalized-cases/{caseId}/deeds");
var deeds = await deedsResponse.Content.ReadFromJsonAsync<JsonElement>();
Scenario 7 β Work with Custom Data
Read and write custom fields on journalized cases, deeds, or documents.
Read custom data
GET /v8.0/journalized-cases/{id}/custom-data
Write custom data
PUT /v8.0/journalized-cases/{id}/custom-data
Content-Type: application/json
{
"bkStr1": "Project Alpha",
"bkStr2": "Phase 2",
"bkInt8": 42,
"bkFloat5": 99.95
}
For details on how custom fields map to Platina's
tCustomDatatable, see Custom Data Support.
Scenario 8 β Update and Finish a Case
Update a journalized case
PATCH /v8.0/journalized-cases/{id}
Content-Type: application/json
{
"title": "Building permit β Storgatan 12 (APPROVED)",
"description": "Updated: permit granted 2025-04-15."
}
Finish (close) a journalized case
POST /v8.0/finished-journalized-cases
Content-Type: application/json
{
"journalizedCaseId": "<case-api-id>"
}
Scenario 9 β Manage Handling Officers and Initiators
Add a handling officer to a case
POST /v8.0/journalized-cases/{id}/handling-officers
Content-Type: application/json
{
"id": "<officer-api-id>",
"message": "Forwarded for legal review",
"isMain": false
}
Add an initiator to a case
POST /v8.0/journalized-cases/{id}/initiators
Content-Type: application/json
{
"name": "Karin Karlsson",
"email": "karin@example.com",
"city": "GΓΆteborg"
}
Remove a handling officer
DELETE /v8.0/journalized-cases/{id}/handling-officers/{officerId}
Complete Workflow Example
A typical integration follows this pattern:
1. Authenticate β Get Bearer token
2. Discover β GET /diaries, GET /reference-data/*
3. Create case β POST /diaries/{id}/journalized-cases
4. Upload documents β POST /journalized-cases/{id}/documents/from-file
5. Add deeds β POST /journalized-cases/{id}/deeds
6. Set custom data β PUT /journalized-cases/{id}/custom-data
7. Finish case β POST /finished-journalized-cases
Error Handling
The API uses standard HTTP status codes:
| Code | Meaning | Action |
|---|---|---|
| 200 | Success | Process the response |
| 201 | Created | Resource created β check Location header |
| 400 | Bad Request | Fix validation errors in request body |
| 401 | Unauthorized | Token expired or invalid β re-authenticate |
| 404 | Not Found | Resource doesn't exist or user lacks access |
| 409 | Conflict | Request contradicts Platina settings (e.g. missing business code) |
| 500 | Server Error | Contact support; check server logs |
Error responses include a JSON body with details:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Bad Request",
"status": 400,
"errors": {
"title": ["The title field is required."]
}
}