SoftSDC v3
API

API Reference

Complete API documentation for SoftSDC integration

The SoftSDC API enables external applications to communicate with the fiscal service for receipt processing and system monitoring. All communication uses REST principles with JSON payloads over HTTP.

Base URL

http://localhost:8431/api/v3

The default port is 8431, but this can be configured in application settings if needed.

Authentication

The API uses PIN-based authentication. Before processing invoices, you must verify the PIN:

POST /api/v3/pin

Core Endpoints

Verify PIN

Authenticate with the smart card before processing invoices.

POST /api/v3/pin
Accept: application/json
Content-Type: application/json

{
  "pin": "1234"
}

Or as plain text:

POST /api/v3/pin
Content-Type: text/plain

1234
0100

Success code indicating PIN is correct.

  • 0100 - PIN correct, command executed successfully
  • 2100 - Incorrect PIN
  • 2110 - Card locked (exceeded attempts)
  • 1300 - Smart card not inserted
  • 2220 - Cannot connect to Secure Element

Create Invoice

Submit receipts for fiscalization.

POST /api/v3/invoices

{
  "dateAndTimeOfIssue": "2024-01-15T10:30:00.000Z",
  "cashier": "123456789",
  "buyerId": "RS34564565",
  "buyerCostCenterId": "567546",
  "invoiceType": "Normal",
  "transactionType": "Sale",
  "payment": [
    {
      "amount": 68.46,
      "paymentType": "Cash"
    }
  ],
  "invoiceNumber": "POS2024/001",
  "referentDocumentNumber": "",
  "options": {
    "omitQRCodeGen": "0",
    "omitTextualRepresentation": "0"
  },
  "items": [
    {
      "name": "Product Name",
      "quantity": 2,
      "unitPrice": 34.23,
      "labels": ["A"],
      "totalAmount": 68.46
    }
  ]
}
{
  "verificationUrl": "https://verify.taxauthority.com/...",
  "verificationQRCode": "data:image/png;base64,...",
  "journal": "============ FISCAL INVOICE ============\n...",
  "messages": "Success",
  "signedBy": "GFB38TO0",
  "encryptedInternalData": "...",
  "signature": "...",
  "totalCounter": 16,
  "transactionTypeCounter": 6,
  "totalAmount": 68.46,
  "taxGroupRevision": 2,
  "businessName": "Company Name",
  "tin": "TAXID123",
  "locationName": "Store Name",
  "address": "Street Address",
  "district": "City",
  "mrc": "99-0100-GFB38TO0"
}

Required Headers:

Accept: application/json
Content-Type: application/json

Optional Headers:

RequestId: <unique-id>  # For tracking (max 32 chars)
Accept-Language: en-US;sr-Cyrl-RS  # Preferred languages

Get Status

Check system operational status.

GET /api/v3/status
Accept: application/json
{
  "isPinRequired": true,
  "auditRequired": false,
  "sdcDateTime": "2024-01-15T10:30:00.000Z",
  "lastInvoiceNumber": "CL4KBJCE-CL4KBJCE-1",
  "protocolVersion": "1.0.0.0",
  "hardwareVersion": "1.0.0.0",
  "softwareVersion": "1.0.0.0",
  "mssc": ["6001"],
  "gsc": ["0100"],
  "deviceSerialNumber": "99-3010-22222222",
  "make": "SoftSDC",
  "model": "v3.0",
  "supportedLanguages": ["en-US", "sr-Cyrl-RS"],
  "uid": "TK7SV2AY",
  "taxCoreApi": "https://api.taxcore.com/",
  "currentTaxRates": {
    "validFrom": "2024-01-01T00:00:00Z",
    "groupId": 2,
    "taxCategories": [
      {
        "name": "VAT",
        "categoryType": 0,
        "taxRates": [
          {
            "rate": 9,
            "label": "A"
          },
          {
            "rate": 0,
            "label": "B"
          }
        ],
        "orderId": 1
      }
    ]
  }
}

Get Environment Parameters

Retrieve environment configuration.

GET /api/v3/environment-parameters

Response:

{
  "organizationName": "Tax Authority",
  "serverTimeZone": "Europe/Belgrade",
  "street": "Main Street 1",
  "city": "Belgrade",
  "country": "RS",
  "endpoints": {
    "taxpayerAdminPortal": "https://portal.taxcore.com/",
    "taxCoreApi": "https://api.taxcore.com/",
    "vsdc": "https://vsdc.taxcore.com/",
    "root": "https://verify.taxcore.com/"
  },
  "environmentName": "PRODUCTION",
  "ntpServer": "http://time.nist.gov/",
  "supportedLanguages": ["en-US", "sr-Latn-RS"]
}

Health Check

Simple availability check.

GET /api/v3/attention

Returns 200 OK if service is running.

Invoice Types

Transaction Types

  • Sale - Normal sale transaction
  • Refund - Return/refund transaction

Invoice Types

  • Normal - Standard fiscal invoice
  • Copy - Duplicate of existing invoice
  • Training - Training mode (non-fiscal)
  • Proforma - Proforma invoice
  • Advance - Advance payment invoice

Payment Types

  • Cash - Cash payment
  • Card - Credit/debit card
  • Check - Check payment
  • WireTransfer - Bank transfer
  • Voucher - Voucher/coupon
  • MobileMoney - Mobile payment

Tax Labels

Tax labels identify the tax category for each item. Common labels:

  • A - Standard VAT rate
  • B - Reduced VAT rate
  • C - VAT exempt
  • D - Special tax category
  • E - Service tax
  • N - No tax

Always use tax labels that match your configured tax rates. Invalid labels will result in error 2310.

Error Handling

Status Codes

All responses use standard HTTP status codes:

  • 200 - Success
  • 400 - Bad Request (invalid data)
  • 401 - Unauthorized (PIN required)
  • 500 - Internal Server Error

Error Response Format

{
  "code": "2100",
  "message": "PIN verification failed",
  "details": "Invalid PIN provided"
}

Common Error Codes

CodeTypeDescription
0000InfoAll OK
0100InfoPIN verified successfully
1300WarningSmart card not present
1400WarningAudit required
1500WarningPIN required
2100ErrorIncorrect PIN
2110ErrorCard locked
2210ErrorSE locked
2310ErrorInvalid tax labels
2400ErrorNot configured
2800ErrorRequired field missing

Best Practices

Request Handling

  1. Always verify PIN first before sending invoices
  2. Include RequestId for tracking and debugging
  3. Handle timeouts gracefully (recommend 30s timeout)
  4. Retry logic for network failures (with exponential backoff)

Performance Tips

  1. Keep connections alive with HTTP keep-alive
  2. Batch operations when possible
  3. Cache status responses for 30-60 seconds
  4. Monitor response times for degradation
  5. Implement circuit breakers for resilience

Integration Examples

Basic Integration Flow

sequenceDiagram
    POS->>API: POST /pin (authenticate)
    API-->>POS: 0100 (success)
    POS->>API: GET /status (check ready)
    API-->>POS: System status
    POS->>API: POST /invoices (create invoice)
    API-->>POS: Signed invoice with URL
    POS->>Customer: Print receipt with QR

Sample Implementations

class SoftSDCClient {
  constructor(baseUrl = 'http://localhost:8431/api/v3') {
    this.baseUrl = baseUrl;
  }

  async verifyPin(pin) {
    const response = await fetch(`${this.baseUrl}/pin`, {
      method: 'POST',
      headers: { 'Content-Type': 'text/plain' },
      body: pin
    });
    return await response.text();
  }

  async createInvoice(invoice) {
    const response = await fetch(`${this.baseUrl}/invoices`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      },
      body: JSON.stringify(invoice)
    });
    return await response.json();
  }
}
import requests
import json

class SoftSDCClient:
    def __init__(self, base_url='http://localhost:8431/api/v3'):
        self.base_url = base_url

    def verify_pin(self, pin):
        response = requests.post(
            f'{self.base_url}/pin',
            data=pin,
            headers={'Content-Type': 'text/plain'}
        )
        return response.text

    def create_invoice(self, invoice):
        response = requests.post(
            f'{self.base_url}/invoices',
            json=invoice,
            headers={'Accept': 'application/json'}
        )
        return response.json()
public class SoftSDCClient
{
    private readonly HttpClient _client;
    private readonly string _baseUrl;

    public SoftSDCClient(string baseUrl = "http://localhost:8431/api/v3")
    {
        _baseUrl = baseUrl;
        _client = new HttpClient();
    }

    public async Task<string> VerifyPin(string pin)
    {
        var content = new StringContent(pin, Encoding.UTF8, "text/plain");
        var response = await _client.PostAsync($"{_baseUrl}/pin", content);
        return await response.Content.ReadAsStringAsync();
    }

    public async Task<InvoiceResponse> CreateInvoice(Invoice invoice)
    {
        var json = JsonSerializer.Serialize(invoice);
        var content = new StringContent(json, Encoding.UTF8, "application/json");
        var response = await _client.PostAsync($"{_baseUrl}/invoices", content);
        var responseJson = await response.Content.ReadAsStringAsync();
        return JsonSerializer.Deserialize<InvoiceResponse>(responseJson);
    }
}
public class SoftSDCClient {
    private final String baseUrl;
    private final HttpClient client;

    public SoftSDCClient(String baseUrl) {
        this.baseUrl = baseUrl;
        this.client = HttpClient.newHttpClient();
    }

    public String verifyPin(String pin) throws Exception {
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(baseUrl + "/pin"))
            .header("Content-Type", "text/plain")
            .POST(HttpRequest.BodyPublishers.ofString(pin))
            .build();

        HttpResponse<String> response = client.send(
            request, HttpResponse.BodyHandlers.ofString()
        );
        return response.body();
    }

    public String createInvoice(String invoiceJson) throws Exception {
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(baseUrl + "/invoices"))
            .header("Content-Type", "application/json")
            .header("Accept", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(invoiceJson))
            .build();

        HttpResponse<String> response = client.send(
            request, HttpResponse.BodyHandlers.ofString()
        );
        return response.body();
    }
}

Testing

Test Mode

Use invoice type Training for testing without fiscal impact:

{
  "invoiceType": "Training",
  // ... rest of invoice data
}

Test Endpoints

During development, you can use these endpoints for testing:

  • GET /api/v3/attention - Check if service is running
  • POST /api/v3/test-invoice - Generate test invoice (if enabled)

Training mode invoices are marked clearly and do not count toward fiscal reporting.