X/ XNet API Developer guide
API v1 · Комплетен contract

XNet · HTTPS · JSON

API патоказ за програмери.

Практичен водич за сигурна интеграција со XNet: еден endpoint, предвидлив JSON договор и корелирани одговори за секое барање.

POST https://vps.xnet.mk:50443/api/commands

01 · Quickstart

Од идеја до прв успешен повик

Сите команди се испраќаат како UTF-8 JSON преку HTTPS. За секое барање креирајте нови идентификатори и краток рок на важност.

01

Подгответе клиент

Користете HTTPS клиент со JSON поддршка и разумен timeout. Заглавието Content-Type мора да биде application/json.

02

Создајте envelope

Генерирајте нов messageId, стабилен clientSessionId и conversation id. Започнете со turn 1.

03

Додадете credentials

Секое барање содржи username и password; заштитените операции ги проверуваат директно во Users кешот.

04

Поврзете го одговорот

Проверете HTTP статус, status и error. replyToMessageId секогаш треба да одговара на испратениот messageId.

!

Адреса на сервисот: Документацијата е на api.xnet.mk, а API повиците одат на vps.xnet.mk со задолжителната порта 50443. Користете ја целата адреса прикажана погоре; портата 443 моментално не е API endpoint.

02 · Contract

Еден envelope за секоја команда

Структурата е верзионирана и обезбедува следливост меѓу апликации, клиенти и разговори. Полето data секогаш е JSON object.

request-envelope.json
{
  "schemaVersion": 1,
  "messageId": "<new-uuid>",
  "authentication": {
    "username": "<username>",
    "password": "<password>"
  },
  "client": {
    "appId": "idiot.mk",
    "appVersion": "1.0.0",
    "clientSessionId": "<session-uuid>"
  },
  "conversation": {
    "id": "<conversation-uuid>",
    "turn": 1
  },
  "operation": "system.ping",
  "sentAtUtc": "<current-utc-time>",
  "expiresAtUtc": "<short-future-utc-time>",
  "data": {}
}
ПолеТипЗначење
schemaVersionintegerМора да биде 1.
messageIdUUIDНов, непразен идентификатор за секое барање.
authentication.username
authentication.password
stringЗадолжителни во секое барање; кај заштитените операции се проверуваат преку Users кешот.
clientobjectИдентитет на апликацијата, верзија и непразен session UUID.
conversationobjectНепразен id и turn поголем од 0.
operationstringИмето на серверската функционалност.
expiresAtUtcISO 8601 / nullАко е зададено, мора да биде во иднина.
dataobjectПараметри за операцијата; никогаш JSON запишан како string.

03 · Operations

Достапни функционалности

Еден contract ги покрива автентикацијата, јавниот feed, објавувањето, гласањето, коментарите, пријавите и администраторската модерација.

READ

system.ping

Проверува дали сервисот прифаќа и обработува валидни команди.

200
data / response
// request.data
{}

// response.data
{ "text": "pong" }
WRITE

user.register

Креира корисник директно во Hetz базата без stored procedure, го mirror-запишува во локалниот кеш и враќа основни податоци.

201
response.data
{
  "userId": 123,
  "username": "developer",
  "email": "dev@example.com",
  "confirmed": true,
  "emailDelivery": "not-required"
}
КатегоријаoperationauthenticationНамена
Authuser.confirm-email
user.resend-confirmation
credentials presentЗадржани за компатибилност; email потврдата привремено не е потребна.
Authuser.login
user.me
verified credentialsПроверка на username/password и враќање безбеден профил без токени.
Finmathcatalog.country-city
finmath.company.register
finmath.company.delete-or-archive
finmath.bookkeeping.register
finmath.bookkeeping.clients
verified credentialsКаталог, регистрација, реални фирма-до-фирма врски и интерни фирми од базата на книговодството, без директна клиентска MySQL конекција.
Обврскиobvrski.list
obvrski.save
obvrski.delete
obvrski.reorder
obvrski.step.save
obvrski.step.delete
verified credentialsЧитање, промена и зачуван редослед само на обврските и нивните чекори за најавениот корисник во фиксната база 09_obvrski. Клиентот користи appId: "obvrski" и не избира база.
Feedpost.list
post.get
post.comment.list
credentials presentЈавни одобрени објави и коментари.
Contentpost.create
post.my
post.vote
post.comment.create
post.report
verified credentialsОбјавување, сопствена историја и интеракции.
Adminadmin.post.pending
admin.post.moderate
admin.report.list
admin.report.resolve
verified credentials + adminОдобрување објави и обработка на пријави.

04 · user.register

Регистрација и автентикација

Секое барање содржи username и password. Нема access/refresh токени или серверски сесии; заштитените операции ги проверуваат credentials преку Users кешот.

user.confirm-email

Привремено не е потребно. Новите и постојните сметки серверот ги смета за потврдени.

user.login

Испрати username и password во authentication; успешниот одговор нема токени.

user.me

Ги проверува credentials повторно и враќа безбеден профил и isAdmin.

CORS · rate limit

Дозволени се idiot.mk origins. Ограничувањето е 120 барања во минута по IP.

ПолеУсловВалидација
usernameЗадолжително3–45 знаци, без празни места.
passwordЗадолжително8–256 знаци. Се испраќа само преку HTTPS.
emailЗадолжителноВалидна адреса, најмногу 60 знаци.
name, surnameОпционалноНајмногу 45 знаци по поле.
pid, address, city, country, phoneОпционалноНајмногу 45 знаци по поле.
languageIdОпционалноЦел број од 1 до 127; стандардно 1.
birthdayОпционалноYYYY-MM-DD; не смее да биде во иднина.
primeRegistrantОпционалноНајмногу 45 знаци.
profilePictureОпционалноString до 700.000 знаци; избегнувајте го кога не е неопходно.

Безбедност: Лозинката не се враќа во одговорот и се зачувува како PBKDF2-SHA256 hash. Не логирајте password или profilePicture во клиентската апликација.

05 · Finmath 3

Најава и регистрација на фирма за Finmath 3

Клиентот користи appId finmath-3. По најавата, response.data.finmath го содржи корисничкиот профил и сите достапни фирми; клиентот не се поврзува директно на MySQL.

user.login

По проверка на credentials враќа finmath.connections за избор на фирма или книговодство, без токени.

catalog.country-city

Со проверени username/password ги враќа активните држави и градови на mk, en или sq.

finmath.company.register

Бара одобрена книговодствена конекција, запишува директно во Hetz базата без stored procedures и го освежува локалниот kesh.

finmath.company.delete-or-archive

Проверува само zz_NNNNNNN_* табели. Непразна табела ја архивира фирмата; ако сите се празни, во deleted_companies LIKE 00_x.log_root ги зачувува целата фирма и сите user-connections како JSON, па ги брише само тие централни редови.

finmath.bookkeeping.register

Креира книговодство со нова база со следниот слободен 04_ реден број и одобрена улога FinmathAccounter.

finmath.bookkeeping.clients

Ги спојува активните реални фирми од company_relations со валидните интерни фирми од my_settings и активните директни интерни конекции за истата книговодствена база. Позитивен ID и непразен краток назив се задолжителни; дозволен е и назив од еден знак, а zz_ работни табели не се услов.

root.data

Сите legacy Data_In повици од shared root одат во Listener. Нема повик или fallback кон 00.get_data; Listener проверува пристап и ја рутира конкретната операција. При MySQL 1146 за побарана фирмена табела, ја обновува од соодветниот 00_x шаблон и ја повторува операцијата еднаш.

finmath.company.register / data
{
  "bookkeepingConnectionId": 321,
  "password": "user-password",
  "shortName": "firma_2026",
  "wholeName": "Фирма ДООЕЛ Скопје",
  "address": "Партизанска",
  "number": "10",
  "city": "Скопје",
  "country": "Македонија",
  "taxNumber": "MK1234567",
  "pid": "1234567",
  "taxObligated": true,
  "planType": 1,
  "accountantPlan": 1,
  "kontenPlanSource": 1,
  "sourceType": 1
}

06 · Responses

Одговор што може сигурно да се следи

Успешен одговор има status completed и error null. Одбиено барање има status rejected, data null и структуриран error. Кај MySQL грешка се враќаат бројот, SQL state, конкретната порака и безбедна конекциска дијагностика без лозинката.

messageId

Клиентот генерира уникатен идентификатор.

replyToMessageId

Серверот го враќа истиот id за корелација.

nextExpectedTurn

Го покажува следниот turn во разговорот.

HTTPКогаВообичаен error.code
200Успешен system.ping.
201Успешна регистрација.
400Невалиден envelope или непозната операција.unsupported-version, invalid-client, unsupported-operation
401Недостасуваат или не се точни credentials.missing-credentials, invalid-credentials
403Недоволни администраторски права.admin-required
408Истечено барање.message-expired
409Корисничкото име или email веќе постои.user-already-exists
422Невалидни податоци за регистрација.validation-error
429Надминато ограничување по IP.rate-limit-exceeded
503Регистрациската база е недостапна.database-unavailable, database-error

06 · Examples

Повик што можете веднаш да го приспособите

Примерот автоматски создава свежи UUID вредности и рок од пет минути, за да не копирате истечено барање.

cURL · system.ping
JavaScript · fetch
const now = new Date();
const payload = {
  schemaVersion: 1,
  messageId: crypto.randomUUID(),
  authentication: { username: "<username>", password: "<password>" },
  client: {
    appId: "idiot.mk",
    appVersion: "1.0.0",
    clientSessionId: crypto.randomUUID()
  },
  conversation: { id: crypto.randomUUID(), turn: 1 },
  operation: "system.ping",
  sentAtUtc: now.toISOString(),
  expiresAtUtc: new Date(now.getTime() + 5 * 60_000).toISOString(),
  data: {}
};

const response = await fetch("https://vps.xnet.mk:50443/api/commands", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(payload),
  signal: AbortSignal.timeout(15_000)
});

const result = await response.json();
if (!response.ok || result.status !== "completed") {
  throw new Error(result.error?.code ?? `HTTP ${response.status}`);
}

07 · Checklist

Правила за стабилна интеграција

Овие правила треба да бидат дел од секоја клиентска имплементација, без оглед на програмскиот јазик.

Нови идентификатори

Не реупотребувајте messageId. Задржете clientSessionId само додека работи една клиентска инстанца.

UTC насекаде

Испраќајте ISO 8601 UTC времиња и краток expiresAtUtc за да се одбиваат застарени команди.

Безбедни логови

Редактирајте лозинки и големи бинарни/string полиња пред логирање.

Контролирано повторување

Не повторувајте write операција автоматски. error.retryable моментално е false.

08 · Codex bridge

Безбеден мост со теренски комуникатори

Теренските комуникатори одржуваат TLS WebSocket конекција и се докажуваат со сопствен ECDSA P-256 клуч и server challenge. Приватниот клуч останува DPAPI-заштитен на теренскиот компјутер; нема заеднички клуч, XNet корисник или лозинка.

Listener-от извршува команди само преку loopback каналот. Оддалечен агент пристапува преку посебен gateway контролиран со XNet Update API клуч; ова не е дел од business API и не користи корисничко име или лозинка.