REST API v1

API документация

Публично ръководство и машинно-четими ресурси за интеграция с ProBG Time Tracking.

Основен API адрес
https://www.tracker.probg.com/api/v1
Готови ресурси за интеграция

REST API v1

API v1 на ProBG Time Tracking предоставя достъп само за четене до клиенти, проекти и отчетено време на текущия Account. API е предназначено за CRM/ERP интеграции, BI справки, външни отчети и синхронизация на данни.

API никога не приема account_id от външната система за избор на Account. Account-ът се определя единствено от Bearer token-а.

Бърз старт

  1. Отворете API в администрацията като Account Administrator.
  2. Създайте отделен token за конкретната интеграция.
  3. Дайте само необходимите права: clients:read, projects:read и/или time:read.
  4. Копирайте token-а веднага — пълната му стойност се показва само веднъж.
  5. Изпращайте token-а с всеки request чрез HTTP Bearer authentication.
curl -H "Authorization: Bearer <TOKEN>" \
  -H "Accept: application/json" \
  "https://www.tracker.probg.com/api/v1/clients"

Достъп по план

API работи само когато Account-ът има активен entitlement api.

По подразбиране API е включено в плановете:

  • Agency
  • Enterprise

Platform Administrator може да промени entitlement-а на ниво план или чрез Account override.

Съществуващ token спира да работи веднага, ако:

  • бъде отнет;
  • срокът му изтече;
  • Account-ът бъде спрян;
  • текущият subscription вече няма API entitlement.

Authentication

Base URL:

https://www.tracker.probg.com/api/v1

Задължителни headers:

Authorization: Bearer ptt_...
Accept: application/json

Token-ите са Account-scoped. В базата се пази само SHA-256 hash; plaintext стойността не може да бъде възстановена.

Срок на token

При създаване може да изберете:

  • 30 дни;
  • 90 дни;
  • 365 дни;
  • без автоматично изтичане.

Token без автоматично изтичане трябва да бъде ръчно отнет, когато интеграцията вече не се използва.

Права

Scope Позволява
clients:read Списък и детайли на клиенти
projects:read Списък и детайли на проекти
time:read Списък и детайли на отчетено време

Token без необходимото право получава HTTP 403 и error.code = insufficient_scope.

Препоръка: не давайте и трите права, ако интеграцията използва само един ресурс.

Ограничение на заявките

На token:

  • 120 requests / минута;
  • 3000 requests / час.

Допълнителен IP safety ceiling:

  • 600 requests / минута;
  • 10 000 requests / час.

При достигане на лимит Laravel връща HTTP 429 Too Many Requests.

Pagination

Всички list endpoints използват pagination.

Параметър:

Параметър Тип По подразбиране Ограничение
page integer 1 Номер на страницата
per_page integer 25 1–100

Примерна структура:

{
  "data": [],
  "meta": {
    "current_page": 1,
    "per_page": 25,
    "last_page": 1,
    "total": 0
  },
  "links": {
    "first": "...",
    "last": "...",
    "prev": null,
    "next": null
  }
}

Използвайте links.next, докато стойността стане null.

Формати на данните

  • Дати без час: YYYY-MM-DD.
  • Date/time стойности: ISO 8601.
  • Продължителност: секунди.
  • Паричните decimal стойности се връщат като decimal strings или null, за да не се губи точност.
  • Всички responses са JSON.
  • ID стойностите са integer.

Clients

GET /clients

Изисква clients:read.

Връща клиенти от Account-а на token-а.

Филтри

Параметър Тип Описание
q string, max 100 Търси по име, фирма, лице за контакт, имейл и фирмен идентификатор
status enum active (default), inactive, archived, all
updated_since date/datetime Само записи, обновени след посочения момент
per_page integer 1–100

Пример:

curl -H "Authorization: Bearer <TOKEN>" \
  -H "Accept: application/json" \
  "https://www.tracker.probg.com/api/v1/clients?status=all&updated_since=2026-10-01T00:00:00%2B03:00&per_page=50"

Полета на Client

Поле Тип
id integer
name string
company string/null
contact_name string/null
email string/null
phone string/null
address string/null
company_id string/null
is_active boolean
projects_count integer
tracked_seconds integer
archived_at ISO 8601/null
created_at ISO 8601/null
updated_at ISO 8601/null

GET /clients/{id}

Изисква clients:read.

Връща един клиент. Архивиран клиент също може да бъде прочетен по ID.

ID от друг Account връща 404, без да разкрива дали ресурсът съществува.

Примерен response:

{
  "data": {
    "id": 42,
    "name": "Example Client",
    "company": "Example Ltd",
    "contact_name": "Jane Doe",
    "email": "jane@example.com",
    "phone": "+359...",
    "address": "Sofia",
    "company_id": "BG123456789",
    "is_active": true,
    "projects_count": 3,
    "tracked_seconds": 184500,
    "archived_at": null,
    "created_at": "2026-09-10T09:20:00+03:00",
    "updated_at": "2026-10-05T17:14:00+03:00"
  }
}

Projects

GET /projects

Изисква projects:read.

Филтри

Параметър Тип Описание
q string, max 100 Търси по име и описание
client_id integer Проекти само за конкретен клиент
status enum active (default), completed, archived, all
updated_since date/datetime Само обновени записи
per_page integer 1–100

Пример:

curl -H "Authorization: Bearer <TOKEN>" \
  -H "Accept: application/json" \
  "https://www.tracker.probg.com/api/v1/projects?client_id=42&status=all"

Полета на Project

Поле Тип Бележка
id integer
client_id integer
client object/null id, name, company
name string
description string/null
status string
billing_model string hourly, fixed_fee, retainer, non_billable
hourly_rate decimal string/null Записаната project rate
effective_hourly_rate decimal string/null Ефективната rate за Hourly проект
billing_currency string Валутата, използвана от проекта
fixed_fee_amount decimal string/null
retainer_amount decimal string/null
estimated_seconds integer/null
tracked_seconds integer
starts_at YYYY-MM-DD/null
ends_at YYYY-MM-DD/null
created_at ISO 8601/null
updated_at ISO 8601/null

В API не се публикуват internal labor-cost snapshots.

GET /projects/{id}

Изисква projects:read.

Връща един проект от текущия Account.

Time entries

GET /time-entries

Изисква time:read.

Филтри

Параметър Тип Описание
client_id integer Само време за клиент
project_id integer Само време за проект
task_id integer Само време за задача
user_id integer Само време на потребител
from YYYY-MM-DD Начална дата, включително
to YYYY-MM-DD Крайна дата, включително; трябва да е >= from
billable boolean true/false или 1/0; празна стойност означава без филтър
billed boolean true/false или 1/0; празна стойност означава без филтър
q string, max 100 Търси в заглавие и описание
updated_since date/datetime Само обновени записи
per_page integer 1–100

Пример за месечен export на проект:

curl -H "Authorization: Bearer <TOKEN>" \
  -H "Accept: application/json" \
  "https://www.tracker.probg.com/api/v1/time-entries?project_id=12&from=2026-10-01&to=2026-10-31&per_page=100"

Полета на Time entry

Поле Тип
id integer
user_id integer/null
client_id integer/null
project_id integer/null
task_id integer/null
user object/null — id, name
client object/null — id, name
project object/null — id, name
task object/null — id, title
work_date YYYY-MM-DD/null
started_at ISO 8601/null
ended_at ISO 8601/null
duration_seconds integer
source string
title string
description string/null
is_billable boolean
is_billed boolean
hourly_rate decimal string/null
amount decimal string/null
created_at ISO 8601/null
updated_at ISO 8601/null

Следните вътрешни полета не се публикуват:

  • cost_rate;
  • cost_amount;
  • private notes.

GET /time-entries/{id}

Изисква time:read.

Връща един time entry от текущия Account.

Error responses

401 — липсващ Bearer token

{
  "error": {
    "code": "unauthenticated",
    "message": "A bearer token is required."
  }
}

401 — невалиден, изтекъл или отнет token

{
  "error": {
    "code": "invalid_token",
    "message": "The API token is invalid, expired, or revoked."
  }
}

403 — Account недостъпен

{
  "error": {
    "code": "account_unavailable",
    "message": "The account is not available."
  }
}

403 — API вече не е включено в subscription-а

{
  "error": {
    "code": "feature_unavailable",
    "message": "API access is not included in the current subscription."
  }
}

403 — липсва scope

{
  "error": {
    "code": "insufficient_scope",
    "message": "The API token does not have the required scope [projects:read]."
  }
}

404 — ресурсът не е достъпен

При неизвестен ID или ID от друг Account се връща 404.

422 — validation error

Невалидни query параметри използват стандартния Laravel JSON validation response:

{
  "message": "The given data was invalid.",
  "errors": {
    "per_page": [
      "The per page field must not be greater than 100."
    ]
  }
}

429 — rate limit

Намалете честотата на заявките и приложете retry/backoff логика.

Практически модели за интеграция

Incremental sync

За периодична синхронизация пазете момента на последния успешно завършен import и при следващия request използвайте updated_since.

GET /clients?updated_since=2026-10-06T08:00:00Z
GET /projects?updated_since=2026-10-06T08:00:00Z
GET /time-entries?updated_since=2026-10-06T08:00:00Z

Не използвайте локалното време на клиента като доказателство, че всички промени са прочетени. Записвайте checkpoint едва след успешното обхождане на всички страници.

Проекти на конкретен клиент

GET /projects?client_id=42&status=all

Отчетено време за период

GET /time-entries?from=2026-10-01&to=2026-10-31&per_page=100

Security препоръки

  • Създавайте отделен token за всяка интеграция.
  • Използвайте минималния необходим набор scopes.
  • Не записвайте token-а в Git, frontend JavaScript, screenshots или публични logs.
  • Пазете го в secret manager / environment variable.
  • Използвайте HTTPS.
  • Отнемайте token-а веднага при компрометиране или спиране на интеграцията.
  • За дългосрочни интеграции планирайте периодична token rotation.
  • При 401 не retry-вайте безкрайно; проверете token lifecycle.
  • При 429 използвайте exponential backoff.

Версиониране

Breaking промени в authentication-а или response contract-а изискват нов namespace, например /api/v2.

В рамките на v1 могат да бъдат добавяни:

  • нови optional response fields;
  • нови optional query filters;
  • нови endpoints.

Интеграциите не трябва да приемат, че response object съдържа само документирaните полета.

Текущи ограничения

API v1 в момента е read-only.

Все още не са част от API v1:

  • създаване/редакция/изтриване на данни;
  • Tasks endpoint;
  • Reports endpoint;
  • Invoices endpoint;
  • Webhooks;
  • OAuth/client credentials;
  • bulk export endpoint.

Тези възможности изискват отделен versioned contract и security review.

Публична документация и Postman

Документацията е достъпна без вход в системата:

  • /api/docs — English;
  • /api/docs/en — English;
  • /api/docs/bg — Български;
  • /api/docs/openapi.yaml — OpenAPI 3.1 specification;
  • /api/docs/postman.json — Postman collection.

Работа с Postman

  1. Изтеглете /api/docs/postman.json.
  2. В Postman изберете Import и импортирайте JSON файла.
  3. Отворете collection variables.
  4. Задайте base_url — по подразбиране е https://tracker.probg.com/api/v1.
  5. Поставете API token-а в token.
  6. При необходимост задайте client_id, project_id и time_entry_id.
  7. Изпращайте готовите requests от папките Clients, Projects и Time Entries.

Bearer authentication е настроено на ниво collection чрез {{token}}. Query параметрите, които не са необходими по подразбиране, са добавени като disabled и могат да бъдат включвани според интеграцията.

OpenAPI

От API документацията в администрацията може да изтеглите OpenAPI 3.1 YAML спецификация за импортиране в Postman, Insomnia, Swagger UI/Editor, Redoc и инструменти за SDK генерация.

Дати и часова зона на checkpoint

updated_since е включителна граница. ISO 8601 стойности с Z, +03:00 и други отмествания се преобразуват към часовата зона на приложението/съхранението преди сравнението. Самостоятелна дата означава полунощ в тази зона; дата и час без отместване също я използват. updated_at се съхранява с точност до секунда; дробна граница след дадена секунда изключва записите от нея. Еквивалентни моменти връщат едни и същи записи.

Използвайте status=all при синхронизация на клиенти или проекти. Филтърът използва собственото updated_at на ресурса; промени в свързани агрегати като tracked_seconds не го обновяват непременно. Няма поток за изтрити записи или фиксиран snapshot между страниците. Интеграциите трябва да припокриват границите, да премахват дубликати по ID и периодично да сверяват всички данни.

Валидация и синхронизация на фактурирания статус

Филтрите billable и billed приемат true/false и 1/0. Празна стойност означава без филтър; други стойности връщат 422. Нулеви, извън допустимия положителен целочислен диапазон, несъществуващи или чужди ресурсни ID връщат 404.

Издаването или анулирането на фактура обновява updated_at на свързаните записи за време в същата транзакция, която променя is_billed. Следващата включителна заявка с updated_since получава тези промени. Заключените часове, ставки и разходи остават непроменени. Повторното действие не измества timestamp-а; неуспешно издаване връща и него назад. При анулиране се следват свързаните исторически записи и след прехвърляне на клиент, като API достъпът остава ограничен до текущия акаунт.

След внедряване съществуващите интеграции трябва еднократно да синхронизират отново всички записи за време: стари промени на фактурирания статус не се попълват със задна дата. Продължават да важат застъпването на checkpoints и периодичната пълна сверка; поток за изтривания и стабилна снимка между страниците остават извън v1.