Tokens, Certificates & Credentials
KSeF token management, certificate enrollment, credentials lifecycle, and MF public keys.
Before submitting invoices to KSeF, a company needs authentication credentials. The Gateway manages three layers:
- Gateway Credentials — KSeF tokens or certificates stored encrypted in the Gateway database
- KSeF Tokens — managed via KSeF API directly on the Ministry of Finance side
- MF Public Keys — encryption keys from the Ministry of Finance (cached, auto-refreshed)
Typical flow: Add KSeF token → Open session (Sessions) → Submit invoices (Invoice Submission)
Credentials (Gateway DB)
Credentials are stored encrypted (Fernet/AES-128) in the Gateway database. They are used when opening KSeF sessions.
Add KSeF Token
The simplest way to authenticate. Get a token from the KSeF portal and store it.
POST /api/companies/{company_id}/credentials/token
Authorization: Bearer {token}
Content-Type: application/json{
"ksef_token": "20260311-EC-4D56D35000-D0583EABAF-4E|nip-8133793363|a7fd8fb...",
"valid_from": "2026-03-11T00:00:00Z",
"valid_to": "2027-03-11T00:00:00Z"
}| Field | Type | Required | Description |
|---|---|---|---|
ksef_token | string | ✅ | Token from KSeF portal (min 10 chars). Encrypted at rest. |
valid_from | datetime | ❌ | Token validity start |
valid_to | datetime | ❌ | Token validity end |
Response (201):
{
"credential_id": "1eade95b-923c-4b7e-8fa1-3906d37c8599",
"company_id": "22919080-f3fe-4aff-8d71-f6493afc956a",
"credential_type": "ksef_token",
"status": "active",
"valid_from": "2026-03-11T22:31:51.828012Z",
"valid_to": null,
"created_at": "2026-03-11T22:31:51.810844Z"
}The token value is never returned after creation. Only a
token_preview(first 4 + last 4 chars) is available via the detail endpoint.
Add Certificate (PEM)
For XAdES-based authentication. Upload a PEM-encoded certificate and private key.
POST /api/companies/{company_id}/credentials
Authorization: Bearer {token}
Content-Type: application/json{
"certificate": "-----BEGIN CERTIFICATE-----\nMIIE...\n-----END CERTIFICATE-----",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----",
"password": "optional-private-key-password"
}List Credentials
GET /api/companies/{company_id}/credentialsReturns all credentials (active and revoked) with their type, status, and validity dates.
Get Active Credential by Type
GET /api/companies/{company_id}/credentials/active/{credential_type}Where {credential_type} is ksef_token or certificate. Returns 404 if no active credential of that type exists.
Get Credential Detail
GET /api/companies/{company_id}/credentials/{credential_id}Includes token_preview (first 4 + last 4 chars) and is_valid boolean.
Revoke Credential
PATCH /api/companies/{company_id}/credentials/{credential_id}
Content-Type: application/json{
"status": "revoked",
"revoked_reason": "Replaced with new token"
}Prefer revocation over deletion — it preserves the audit trail.
Delete Credential
DELETE /api/companies/{company_id}/credentials/{credential_id}Response: 204 No Content. Use only for test/cleanup.
KSeF Tokens (via KSeF API)
These endpoints interact directly with the Ministry of Finance KSeF API.
Generate KSeF Token
POST /api/companies/{company_id}/ksef-tokens
Content-Type: application/json{
"permissions": ["InvoiceWrite", "InvoiceRead", "CredentialsRead", "CredentialsManage"],
"description": "API production token"
}Available permissions:
| Permission | Description |
|---|---|
InvoiceRead | Read invoices |
InvoiceWrite | Submit invoices |
CredentialsRead | Read credentials/permissions |
CredentialsManage | Manage credentials/permissions |
SubunitManage | Manage subunits |
Response (202):
{
"referenceNumber": "20260311-EC-4D56D35000-D0583EABAF-4E",
"token": "20260311-EC-4D56D35000-...|nip-8133793363|a7fd8fb..."
}The
tokenvalue is shown only once. Store it immediately and add it as a credential viaPOST /credentials/token.
List KSeF Tokens
GET /api/companies/{company_id}/ksef-tokensGet Token Status
GET /api/companies/{company_id}/ksef-tokens/{reference_number}Revoke KSeF Token
DELETE /api/companies/{company_id}/ksef-tokens/{reference_number}This is permanent — a revoked KSeF token cannot be reactivated.
Certificate Management (via KSeF API)
Start Automated Enrollment
POST /api/companies/{company_id}/certificates/enroll
Content-Type: application/json{
"certificate_name": "ProductionCert2026",
"certificate_type": "Authentication",
"valid_from": "2026-03-14T00:00:00Z"
}Check Enrollment Status
GET /api/companies/{company_id}/certificates/enroll/{reference_number}/statusOther Certificate Operations
| Method | Endpoint | Description |
|---|---|---|
POST | .../certificates/enrollments | Low-level enrollment (pass CSR) |
GET | .../certificates/enrollments/data | Get enrollment data |
GET | .../certificates/limits | Check enrollment limits |
POST | .../certificates/query | Search certificates |
POST | .../certificates/retrieve | Retrieve by serial |
POST | .../certificates/{serial}/revoke | Revoke certificate |
MF Public Keys
Used internally for encrypting AES-256 symmetric keys and KSeF tokens. The Gateway caches these automatically.
List Public Keys
GET /api/public-keys{
"certificates": [
{
"certificate": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...",
"validFrom": "2025-09-29T06:03:19Z",
"validTo": "2027-09-29T06:03:18Z",
"usage": ["KsefTokenEncryption"]
},
{
"certificate": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...",
"validFrom": "2025-09-29T06:17:45Z",
"validTo": "2027-09-29T06:17:44Z",
"usage": ["SymmetricKeyEncryption"]
}
]
}| Key Usage | Purpose |
|---|---|
KsefTokenEncryption | Encrypt KSeF tokens during authentication |
SymmetricKeyEncryption | Encrypt AES-256-CBC symmetric keys for invoice encryption |
Get Active Key
GET /api/public-keys/activeClear Cache
POST /api/public-keys/clear-cacheForces re-fetch from KSeF. Use when keys have been rotated by the Ministry of Finance.
Authentication Flows
KSeF Token flow (simpler):
1. Gateway reads stored token from DB (decrypts)
2. GET /auth/challenge from KSeF → gets challenge + timestamp
3. GET /security/public-key-certificates → gets MF public key
4. Encrypts token with RSA (MF public key)
5. POST /auth/ksef-token to KSeF → gets session reference
Certificate/XAdES flow (advanced):
1. Gateway reads certificate + private key from DB
2. GET /auth/challenge from KSeF → gets challenge XML
3. Signs challenge XML with XAdES (private key)
4. POST /auth/xades to KSeF → gets session referenceImportant Notes
Token vs Certificate: For most integrations, a KSeF token is sufficient and simpler. Certificates are needed for XAdES authentication or offline invoice signing.
Credential lifecycle: When rotating credentials, add the new credential first (it becomes active), then revoke the old one. This ensures no downtime during rotation.
KSeF token vs Gateway credential: A KSeF token is generated on the KSeF portal. A Gateway credential stores that token encrypted in the Gateway database. You need both.