# Quickstart

URL: https://postman.slovakodata.com/developers/en/rychly-start/
Updated: 2026-07-24

From empty project to a sent invoice.

From empty project to a sent invoice. Examples target the staging
environment.

<li>

### Get an access token

Exchange your `client_id` and `client_secret` for a token. Its lifetime
is in the `expires_in` field.

```bash
curl -X POST https://testpostman.slovakodata.com/sapi/auth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "client_credentials",
    "client_id": "'"$CLIENT_ID"'",
    "client_secret": "'"$CLIENT_SECRET"'"
  }'

# 200 OK
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6...",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_token": "KjxT9m..."
}
```

```ts
const BASE = "https://testpostman.slovakodata.com";

async function getToken(): Promise<string> {
  const res = await fetch(`${BASE}/sapi/auth/token`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      grant_type: "client_credentials",
      client_id: process.env.CLIENT_ID!,
      client_secret: process.env.CLIENT_SECRET!,
    }),
  });

  if (!res.ok) throw new Error(`Auth failed: ${res.status}`);

  const { access_token } = await res.json();
  return access_token;
}
```

```csharp
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;

const string Base = "https://testpostman.slovakodata.com";

async Task<string> GetTokenAsync(HttpClient http)
{
    var payload = new
    {
        grant_type = "client_credentials",
        client_id = Environment.GetEnvironmentVariable("CLIENT_ID")!,
        client_secret = Environment.GetEnvironmentVariable("CLIENT_SECRET")!,
    };

    using var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
    var res = await http.PostAsync($"{Base}/sapi/auth/token", content);
    res.EnsureSuccessStatusCode();

    var body = await res.Content.ReadFromJsonAsync();
    return body!.AccessToken;
}

record TokenResponse(
    [property: JsonPropertyName("access_token")] string AccessToken,
    [property: JsonPropertyName("expires_in")]  int ExpiresIn);
```

</li>

<li>

### Send an invoice

The request body is a JSON envelope — the UBL XML goes as a string into
the `payload` field, alongside metadata (the sender and receiver
participant IDs). Besides the token you also send your Peppol identifier
in the header and an idempotency key.

```bash
curl -X POST https://testpostman.slovakodata.com/sapi/document/send \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Peppol-Participant-Id: 0245:2020317068" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  --data-binary @envelope.json

# envelope.json — the UBL XML itself is a string in the "payload" field
{
  "metadata": {
    "documentId": "INV-2026-0001",
    "documentTypeId": "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1",
    "processId": "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0",
    "senderParticipantId": "0245:2020317068",
    "receiverParticipantId": "0245:1234567890",
    "creationDateTime": "2026-07-13T09:14:22Z"
  },
  "payload": "...",
  "payloadFormat": "XML"
}

# 202 Accepted — taken in for processing
{
  "providerDocumentId": "9f2c1e84-3b7a-4d16-b0c5-1e8a72d40f31",
  "status": "ACCEPTED",
  "receivedAt": "2026-07-13T09:14:22.310Z"
}
```

```ts

async function sendInvoice(token: string, path: string) {
  const xml = await readFile(path, "utf8");

  const res = await fetch(`${BASE}/sapi/document/send`, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${token}`,
      "X-Peppol-Participant-Id": "0245:2020317068",
      "Idempotency-Key": randomUUID(),
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      metadata: {
        documentId: "INV-2026-0001",
        documentTypeId:
          "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1",
        processId: "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0",
        senderParticipantId: "0245:2020317068",
        receiverParticipantId: "0245:1234567890",
        creationDateTime: new Date().toISOString(),
      },
      payload: xml,
      payloadFormat: "XML",
    }),
  });

  // 202 = accepted. The delivery outcome arrives via webhook.
  if (res.status !== 202) {
    const { error } = await res.json();
    throw new Error(`${error.code}: ${error.message}`);
  }

  return res.json();
}
```

```csharp
async Task<string> SendInvoiceAsync(HttpClient http, string token, string path)
{
    var xml = await File.ReadAllTextAsync(path);

    var envelope = new
    {
        metadata = new
        {
            documentId           = "INV-2026-0001",
            documentTypeId       = "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1",
            processId            = "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0",
            senderParticipantId  = "0245:2020317068",
            receiverParticipantId = "0245:1234567890",
            creationDateTime     = DateTimeOffset.UtcNow,
        },
        payload       = xml,
        payloadFormat = "XML",
    };
    var json = JsonSerializer.Serialize(envelope);

    using var req = new HttpRequestMessage(HttpMethod.Post, $"{Base}/sapi/document/send")
    {
        Content = new StringContent(json, Encoding.UTF8, "application/json")
    };

    req.Headers.Authorization = new("Bearer", token);
    req.Headers.Add("X-Peppol-Participant-Id", "0245:2020317068");
    req.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());

    var res = await http.SendAsync(req);
    res.EnsureSuccessStatusCode();

    var body = await res.Content.ReadFromJsonAsync();
    return body!.ProviderDocumentId;
}
```

**202 does not mean delivered.** It only means we accepted the document.
Validation and delivery run asynchronously — you learn the outcome from
a webhook or from the document status.

</li>

<li>

### Receive inbound invoices

The inbound list is cursor-paginated. The detail endpoint returns a JSON
envelope — the XML itself is in the `payload` field and the document
status in the `status` field.

```bash
curl "https://testpostman.slovakodata.com/sapi/document/receive?limit=20" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Peppol-Participant-Id: 0245:2020317068"

# 200 OK
{
  "documents": [
    {
      "documentId": "3c9a77f1-64de-4b02-9f7e-2a1c8d05b4e6",
      "documentTypeId": "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1",
      "processId": "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0",
      "senderParticipantId": "0245:1234567890",
      "receiverParticipantId": "0245:2020317068",
      "creationDateTime": "2026-07-13T08:02:11.004Z",
      "status": "RECEIVED"
    }
  ],
  "totalCount": 1,
  "nextPageToken": "eyJjIjoiMjAyNi0wNy0xM1QwODowMjoxMS4wMDRaIiwidCI6MTc..."
}

# The detail endpoint returns a JSON envelope — pull the XML from payload
curl "$BASE/sapi/document/receive/3c9a77f1-64de-4b02-9f7e-2a1c8d05b4e6" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Peppol-Participant-Id: 0245:2020317068" | jq -r .payload > received.xml

curl -X POST "$BASE/sapi/document/receive/3c9a77f1-.../acknowledge" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Peppol-Participant-Id: 0245:2020317068"
```

**Acknowledge what you take.** Acknowledge a document only once you have
stored it safely on your side. Unacknowledged documents stay in the
list, so an outage never loses one.

</li>
