Getting Started
To start using the API you first need to create an API key. In the Parsek app, go to Settings → API Keys (admin/super_admin only) to generate a new key. The key starts with the pk_ prefix and is shown in full only once, at creation.
Authentication
All /v1/* requests authenticate on every call using the X-API-Key header. Key management endpoints use the app session’s Authorization: Bearer <token> header. Each key only accesses its granted scopes; insufficient permission returns 403 insufficient_scope. Keys are stored hashed on the server and shown only once, at creation.
Rate Limit
Each API key has a per-minute request limit (default 60 req/min, configurable via rate_limit at creation). Every response includes X-RateLimit-Limit and X-RateLimit-Remaining headers; when exceeded you receive 429 + Retry-After. For browser-based calls you can define allowed_domains (origin whitelist) on the key.
Error Codes
| Code | Description |
|---|---|
200 | Success |
400 | Bad request — missing/invalid parameters |
401 | Unauthorized — invalid or missing API key |
403 | Forbidden — origin not allowed / insufficient role |
404 | Resource not found |
429 | Rate limit exceeded |
500 | Server error |
Endpoint Reference Active
Invoices
/api/external/v1/invoices
X-API-Key
scope: einvoice
Create invoice (optionally send)
Creates a new e-Archive/e-Invoice draft. If `send_immediately: true` is passed, the invoice is sent immediately.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
send_immediately | boolean | No | if true, invoice is sent immediately |
customer | object | Yes | Customer info (name required; vkn or tckn) |
lines | array | Yes | Invoice line items (at least 1) |
invoice_type | string | No | Invoice type (default 'SATIS') |
currency | string | No | Currency (default 'TRY') |
issue_date | string (date) | No | Issue date YYYY-MM-DD (default today) |
notes | array | No | Invoice notes |
curl -X POST "https://api.parsekpro.com/api/external/v1/invoices" \
-H "X-API-Key: pk_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"send_immediately":false,"customer":{"name":"Örnek Müşteri A.Ş.","vkn":"1234567890","email":"[email protected]","tax_office":"Kadıköy","address":{"city":"İstanbul","country":"Türkiye"}},"lines":[{"name":"Danışmanlık Hizmeti","quantity":1,"unit_price":1000,"tax_percent":20,"unit_code":"C62"}],"invoice_type":"SATIS","currency":"TRY"}'
const res = await fetch("https://api.parsekpro.com/api/external/v1/invoices", {
method: "POST",
headers: {
'X-API-Key': 'pk_xxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"send_immediately": false,
"customer": {
"name": "Örnek Müşteri A.Ş.",
"vkn": "1234567890",
"email": "[email protected]",
"tax_office": "Kadıköy",
"address": {
"city": "İstanbul",
"country": "Türkiye"
}
},
"lines": [
{
"name": "Danışmanlık Hizmeti",
"quantity": 1,
"unit_price": 1000,
"tax_percent": 20,
"unit_code": "C62"
}
],
"invoice_type": "SATIS",
"currency": "TRY"
})
});
const data = await res.json();
import requests
resp = requests.post(
"https://api.parsekpro.com/api/external/v1/invoices",
headers={ "X-API-Key": "pk_xxxxxxxx" },
json={
"send_immediately": False,
"customer": {
"name": "Örnek Müşteri A.Ş.",
"vkn": "1234567890",
"email": "[email protected]",
"tax_office": "Kadıköy",
"address": {
"city": "İstanbul",
"country": "Türkiye"
}
},
"lines": [
{
"name": "Danışmanlık Hizmeti",
"quantity": 1,
"unit_price": 1000,
"tax_percent": 20,
"unit_code": "C62"
}
],
"invoice_type": "SATIS",
"currency": "TRY"
}
)
print(resp.json())
{
"success": true,
"invoice": {
"id": "9f1c2b7e-...",
"status": "draft",
"payable_amount": 1200
}
}/api/external/v1/invoices
X-API-Key
scope: einvoice
List invoices
Lists the company invoices with pagination. Filterable by `direction` and `status`.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
direction | string | query | No | 'outbound' / 'inbound' |
status | string | query | No | Status (draft, sent, error…) |
page | integer | query | No | Page (0-based, default 0) |
limit | integer | query | No | Page size (default 20) |
curl -X GET "https://api.parsekpro.com/api/external/v1/invoices" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/invoices", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/invoices",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"data": [
{
"id": "9f1c2b7e-...",
"invoice_number": "PSK2026000000123",
"direction": "outbound",
"status": "sent",
"issue_date": "2026-02-10",
"customer_name": "Örnek Müşteri A.Ş.",
"payable_amount": 1200,
"tax_amount": 200
}
],
"total": 42,
"page": 0,
"limit": 20
}/api/external/v1/invoices/{id}
X-API-Key
scope: einvoice
Invoice detail
Returns all fields of a single invoice.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
id | string (uuid) | path | Yes | Invoice ID |
curl -X GET "https://api.parsekpro.com/api/external/v1/invoices/{id}" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/invoices/{id}", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/invoices/{id}",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"id": "9f1c2b7e-...",
"invoice_number": "PSK2026000000123",
"status": "sent",
"payable_amount": 1200,
"lines": [
{
"name": "Danışmanlık Hizmeti",
"quantity": 1,
"unitPrice": 1000,
"taxPercent": 20
}
]
}/api/external/v1/invoices/{id}/status
X-API-Key
scope: einvoice
Query invoice status
Returns the current status code and message of the invoice.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
id | string (uuid) | path | Yes | Invoice ID |
curl -X GET "https://api.parsekpro.com/api/external/v1/invoices/{id}/status" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/invoices/{id}/status", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/invoices/{id}/status",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"id": "9f1c2b7e-...",
"invoice_uuid": "A1B2C3-...",
"status": "sent",
"status_code": 100,
"status_message": null
}/api/external/v1/invoices/{id}/pdf
X-API-Key
scope: einvoice
Download invoice PDF
Returns the invoice PDF output (application/pdf).
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
id | string (uuid) | path | Yes | Invoice ID |
curl -X GET "https://api.parsekpro.com/api/external/v1/invoices/{id}/pdf" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/invoices/{id}/pdf", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/invoices/{id}/pdf",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
application/pdf (binary)/api/external/v1/invoices/{id}/cancel
X-API-Key
scope: einvoice
Cancel e-Archive invoice
Only invoices in the e-Archive (EARSIVFATURA) scenario can be cancelled.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
id | string (uuid) | path | Yes | Invoice ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
cancel_date | string (date) | No | Cancel date (default today) |
curl -X POST "https://api.parsekpro.com/api/external/v1/invoices/{id}/cancel" \
-H "X-API-Key: pk_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"cancel_date":"2026-02-11"}'
const res = await fetch("https://api.parsekpro.com/api/external/v1/invoices/{id}/cancel", {
method: "POST",
headers: {
'X-API-Key': 'pk_xxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"cancel_date": "2026-02-11"
})
});
const data = await res.json();
import requests
resp = requests.post(
"https://api.parsekpro.com/api/external/v1/invoices/{id}/cancel",
headers={ "X-API-Key": "pk_xxxxxxxx" },
json={
"cancel_date": "2026-02-11"
}
)
print(resp.json())
{
"success": true,
"result": {}
}Utilities
/api/external/v1/check-einvoice-user
X-API-Key
scope: einvoice
Check e-Invoice registered user
Checks whether the given VKN/TCKN is a registered e-Invoice (GİB) user.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
vkn | string | No | Tax ID (VKN) |
tckn | string | No | National ID (TCKN) |
curl -X POST "https://api.parsekpro.com/api/external/v1/check-einvoice-user" \
-H "X-API-Key: pk_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"vkn":"1234567890"}'
const res = await fetch("https://api.parsekpro.com/api/external/v1/check-einvoice-user", {
method: "POST",
headers: {
'X-API-Key': 'pk_xxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"vkn": "1234567890"
})
});
const data = await res.json();
import requests
resp = requests.post(
"https://api.parsekpro.com/api/external/v1/check-einvoice-user",
headers={ "X-API-Key": "pk_xxxxxxxx" },
json={
"vkn": "1234567890"
}
)
print(resp.json())
{
"is_einvoice_user": true
}Current Accounts
/api/external/v1/current-accounts
X-API-Key
scope: current_accounts:read
List current accounts
Lists company current accounts with pagination. Filters: `account_type` (CUSTOMER/VENDOR/SUBCONTRACTOR/EMPLOYEE), `status` (ACTIVE/PASSIVE), `q` (name/code search), `updated_since` (delta sync).
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
account_type | string | query | No | CUSTOMER/VENDOR/SUBCONTRACTOR/EMPLOYEE |
status | string | query | No | ACTIVE / PASSIVE |
q | string | query | No | Name/code search |
updated_since | string (ISO8601) | query | No | Updated after this timestamp |
page | integer | query | No | Page (0-based) |
limit | integer | query | No | Page size (max 100) |
curl -X GET "https://api.parsekpro.com/api/external/v1/current-accounts" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/current-accounts", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/current-accounts",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"data": [
{
"id": "uuid",
"account_code": "MUS-00001",
"account_name": "Örnek Müşteri A.Ş.",
"account_type": "CUSTOMER",
"balance": 12500,
"base_currency": "TRY",
"status": "ACTIVE"
}
],
"total": 42,
"page": 0,
"limit": 20
}/api/external/v1/current-accounts/{id}
X-API-Key
scope: current_accounts:read
Current account detail
Returns all fields of a single current account.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
id | string (uuid) | path | Yes | Account ID |
curl -X GET "https://api.parsekpro.com/api/external/v1/current-accounts/{id}" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/current-accounts/{id}", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/current-accounts/{id}",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"id": "uuid",
"account_code": "MUS-00001",
"account_name": "Örnek Müşteri A.Ş.",
"account_type": "CUSTOMER",
"tax_number": "1234567890",
"iban": "TR..",
"balance": 12500,
"base_currency": "TRY",
"status": "ACTIVE"
}/api/external/v1/current-accounts
X-API-Key
scope: current_accounts:write
Create current account
Creates a new current account. If `account_code` is omitted it is auto-generated by type. Supports the `Idempotency-Key` header.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
account_name | string | Yes | Account name |
account_type | string | Yes | CUSTOMER/VENDOR/SUBCONTRACTOR/EMPLOYEE |
account_code | string | No | Auto-generated if empty |
tax_number | string | No | Tax/National ID |
tax_office | string | No | Tax office |
email | string | No | |
phone | string | No | Phone |
iban | string | No | IBAN |
base_currency | string | No | Currency (default TRY) |
curl -X POST "https://api.parsekpro.com/api/external/v1/current-accounts" \
-H "X-API-Key: pk_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"account_name":"Örnek Müşteri A.Ş.","account_type":"CUSTOMER","tax_number":"1234567890","email":"[email protected]","base_currency":"TRY"}'
const res = await fetch("https://api.parsekpro.com/api/external/v1/current-accounts", {
method: "POST",
headers: {
'X-API-Key': 'pk_xxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"account_name": "Örnek Müşteri A.Ş.",
"account_type": "CUSTOMER",
"tax_number": "1234567890",
"email": "[email protected]",
"base_currency": "TRY"
})
});
const data = await res.json();
import requests
resp = requests.post(
"https://api.parsekpro.com/api/external/v1/current-accounts",
headers={ "X-API-Key": "pk_xxxxxxxx" },
json={
"account_name": "Örnek Müşteri A.Ş.",
"account_type": "CUSTOMER",
"tax_number": "1234567890",
"email": "[email protected]",
"base_currency": "TRY"
}
)
print(resp.json())
{
"id": "uuid",
"account_code": "MUS-00007",
"account_name": "Örnek Müşteri A.Ş.",
"account_type": "CUSTOMER",
"status": "ACTIVE",
"base_currency": "TRY"
}/api/external/v1/current-accounts/{id}
X-API-Key
scope: current_accounts:write
Update current account
Updates the given fields (whitelisted fields only).
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
id | string (uuid) | path | Yes | Account ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
account_name | string | No | Account name |
phone | string | No | Phone |
status | string | No | ACTIVE/PASSIVE |
curl -X PUT "https://api.parsekpro.com/api/external/v1/current-accounts/{id}" \
-H "X-API-Key: pk_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"phone":"05551112233","status":"PASSIVE"}'
const res = await fetch("https://api.parsekpro.com/api/external/v1/current-accounts/{id}", {
method: "PUT",
headers: {
'X-API-Key': 'pk_xxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"phone": "05551112233",
"status": "PASSIVE"
})
});
const data = await res.json();
import requests
resp = requests.put(
"https://api.parsekpro.com/api/external/v1/current-accounts/{id}",
headers={ "X-API-Key": "pk_xxxxxxxx" },
json={
"phone": "05551112233",
"status": "PASSIVE"
}
)
print(resp.json())
{
"id": "uuid",
"account_code": "MUS-00001",
"phone": "05551112233",
"status": "PASSIVE"
}/api/external/v1/current-accounts/{id}/balance
X-API-Key
scope: current_accounts:read
Current account balance
Returns debit/credit/net balance and multi-currency balances.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
id | string (uuid) | path | Yes | Account ID |
curl -X GET "https://api.parsekpro.com/api/external/v1/current-accounts/{id}/balance" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/current-accounts/{id}/balance", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/current-accounts/{id}/balance",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"account_id": "uuid",
"debit_balance": 30000,
"credit_balance": 17500,
"balance": 12500,
"balance_base": 12500,
"base_currency": "TRY",
"balances": {
"TRY": 12500
}
}/api/external/v1/current-accounts/{id}/transactions
X-API-Key
scope: current_accounts:read
Current account transactions
Returns account transactions with pagination. `from`/`to` date filter.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
id | string (uuid) | path | Yes | Account ID |
from | string (date) | query | No | Start date |
to | string (date) | query | No | End date |
curl -X GET "https://api.parsekpro.com/api/external/v1/current-accounts/{id}/transactions" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/current-accounts/{id}/transactions", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/current-accounts/{id}/transactions",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"data": [
{
"id": "uuid",
"transaction_date": "2026-02-10",
"transaction_type": "DEBIT",
"amount": 1200,
"currency_code": "TRY",
"description": "Fatura",
"document_number": "PSK2026..."
}
],
"total": 12,
"page": 0,
"limit": 20
}Inventory
/api/external/v1/products
X-API-Key
scope: inventory:read
Product/material catalog
Lists the material catalog. Filters: `q` (name search), `material_type`, `updated_since`.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
q | string | query | No | Name search |
material_type | string | query | No | CONSUMABLE / USABLE |
updated_since | string (ISO8601) | query | No | Delta sync |
page | integer | query | No | Page |
limit | integer | query | No | Size (max 100) |
curl -X GET "https://api.parsekpro.com/api/external/v1/products" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/products", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/products",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"data": [
{
"id": "uuid",
"name": "Çimento CEM I 42.5",
"material_type": "CONSUMABLE",
"minimum_stock_level": 100,
"current_avg_cost": 250,
"sale_price": 300,
"default_currency": "TRY"
}
],
"total": 128,
"page": 0,
"limit": 20
}/api/external/v1/products/{id}
X-API-Key
scope: inventory:read
Product detail
Returns all fields of a single material.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
id | string (uuid) | path | Yes | Material ID |
curl -X GET "https://api.parsekpro.com/api/external/v1/products/{id}" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/products/{id}", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/products/{id}",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"id": "uuid",
"name": "Çimento CEM I 42.5",
"material_type": "CONSUMABLE",
"current_avg_cost": 250,
"total_stock_value": 32000
}/api/external/v1/inventory/levels
X-API-Key
scope: inventory:read
Stock levels
Current stock levels per warehouse/branch. Filters: `material_id`, `branch_id`, `warehouse_location_id`.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
material_id | string (uuid) | query | No | Material filter |
branch_id | string (uuid) | query | No | Branch filter |
warehouse_location_id | string (uuid) | query | No | Warehouse filter |
curl -X GET "https://api.parsekpro.com/api/external/v1/inventory/levels" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/inventory/levels", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/inventory/levels",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"data": [
{
"material_id": "uuid",
"material_name": "Çimento CEM I 42.5",
"branch_id": "uuid",
"warehouse_location_id": "uuid",
"current_quantity": 450,
"total_incoming": 900,
"total_outgoing": 450
}
],
"total": 12,
"page": 0,
"limit": 20
}/api/external/v1/inventory/movements
X-API-Key
scope: inventory:read
Stock movements
Lists stock movements. Filters: `material_id`, `branch_id`, `transaction_type`, `from`/`to`.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
material_id | string (uuid) | query | No | Material |
transaction_type | string | query | No | IN/OUT/ADJUSTMENT… |
from | string (date) | query | No | Start |
to | string (date) | query | No | End |
curl -X GET "https://api.parsekpro.com/api/external/v1/inventory/movements" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/inventory/movements", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/inventory/movements",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"data": [
{
"id": "uuid",
"material_id": "uuid",
"transaction_type": "IN",
"quantity": 100,
"unit_price": 250,
"currency_code": "TRY",
"created_at": "2026-02-10T10:00:00Z"
}
],
"total": 340,
"page": 0,
"limit": 20
}/api/external/v1/warehouses
X-API-Key
scope: inventory:read
Warehouse/location list
Lists warehouses and locations. Filters: `branch_id`, `is_active`.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
branch_id | string (uuid) | query | No | Branch |
is_active | boolean | query | No | Active filter |
curl -X GET "https://api.parsekpro.com/api/external/v1/warehouses" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/warehouses", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/warehouses",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"data": [
{
"id": "uuid",
"code": "DEPO-01",
"name": "Merkez Depo",
"location_path": "Merkez Depo",
"is_active": true
}
],
"total": 6,
"page": 0,
"limit": 20
}/api/external/v1/inventory/movements
X-API-Key
scope: inventory:write
Create stock movement
Stock in/out/adjustment. `transaction_type`: IN, OUT, ADJUSTMENT, COUNT_ADJUSTMENT. Stock level and valuation (FIFO/Average) are updated automatically. 409 on insufficient stock for OUT. Supports `Idempotency-Key`.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
material_id | string (uuid) | Yes | Material ID |
transaction_type | string | Yes | IN/OUT/ADJUSTMENT/COUNT_ADJUSTMENT |
quantity | number | Yes | Quantity (positive) |
branch_id | string (uuid) | No | Branch (required in location mode) |
warehouse_location_id | string (uuid) | No | Warehouse location |
unit_price | number | No | Unit price (valuation for IN) |
notes | string | No | Note |
curl -X POST "https://api.parsekpro.com/api/external/v1/inventory/movements" \
-H "X-API-Key: pk_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"material_id":"uuid","transaction_type":"IN","quantity":100,"unit_price":250,"notes":"Satın alma girişi"}'
const res = await fetch("https://api.parsekpro.com/api/external/v1/inventory/movements", {
method: "POST",
headers: {
'X-API-Key': 'pk_xxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"material_id": "uuid",
"transaction_type": "IN",
"quantity": 100,
"unit_price": 250,
"notes": "Satın alma girişi"
})
});
const data = await res.json();
import requests
resp = requests.post(
"https://api.parsekpro.com/api/external/v1/inventory/movements",
headers={ "X-API-Key": "pk_xxxxxxxx" },
json={
"material_id": "uuid",
"transaction_type": "IN",
"quantity": 100,
"unit_price": 250,
"notes": "Satın alma girişi"
}
)
print(resp.json())
{
"id": "uuid",
"material_id": "uuid",
"transaction_type": "IN",
"quantity": 100,
"unit_price": 250,
"currency_code": "TRY",
"created_at": "2026-02-10T10:00:00Z"
}Attendance / PDKS
/api/external/v1/employees
X-API-Key
scope: attendance:read
Employee directory (mapping)
Returns the employee directory for PDKS card/number mapping. Filters: `q`, `status`, `branch_id`, `updated_since`.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
q | string | query | No | Name / number / card search |
status | string | query | No | active / passive |
updated_since | string (date) | query | No | ISO8601 delta sync |
curl -X GET "https://api.parsekpro.com/api/external/v1/employees" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/employees", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/employees",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"data": [
{
"id": "uuid",
"employee_number": "SICIL-9001",
"pdks_card_no": "CARD-001",
"first_name": "Ali",
"last_name": "Yılmaz",
"full_name": "Ali Yılmaz",
"tc_identity_no": "12345678901",
"branch_id": "uuid",
"status": "active"
}
],
"total": 42,
"page": 0,
"limit": 20
}/api/external/v1/attendance
X-API-Key
scope: attendance:read
Daily attendance records
Lists daily attendance records. Filters: `employee_id`, `branch_id`, `status_code`, `date`, `from`/`to`.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
employee_id | string (uuid) | query | No | Employee |
status_code | string | query | No | X/I/R/YG/DD/UI |
from | string (date) | query | No | Start (YYYY-MM-DD) |
to | string (date) | query | No | End (YYYY-MM-DD) |
curl -X GET "https://api.parsekpro.com/api/external/v1/attendance" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/attendance", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/attendance",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"data": [
{
"id": "uuid",
"employee_id": "uuid",
"date": "2026-02-10",
"status_code": "X",
"work_hours": 9.5,
"overtime_hours": 1.5,
"check_in_time": "2026-02-10T05:00:00Z",
"check_out_time": "2026-02-10T14:30:00Z",
"source": "pdks_api"
}
],
"total": 120,
"page": 0,
"limit": 20
}/api/external/v1/attendance/punches
X-API-Key
scope: attendance:read
Raw PDKS punch events
Returns raw device punch events (debug/audit). Filters: `employee_id`, `device_id`, `matched`, `from`/`to`.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
employee_id | string (uuid) | query | No | Employee |
device_id | string | query | No | Device ID |
matched | boolean | query | No | Match status |
curl -X GET "https://api.parsekpro.com/api/external/v1/attendance/punches" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/attendance/punches", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/attendance/punches",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"data": [
{
"id": "uuid",
"employee_id": "uuid",
"card_no": "CARD-001",
"device_id": "GATE-1",
"direction": "IN",
"punch_time": "2026-02-10T05:00:00Z",
"attendance_date": "2026-02-10",
"matched": true,
"source": "pdks_api"
}
],
"total": 240,
"page": 0,
"limit": 20
}/api/external/v1/attendance
X-API-Key
scope: attendance:write
PDKS attendance push (punch or daily)
Two modes for PDKS hardware/integrators: (1) `punches` — raw in/out events are pushed; daily attendance (work hours via IN→OUT pairing) is computed automatically; resends are idempotent (dedup). (2) `records` — daily attendance is written directly (`status_code`: X/I/R/YG/DD/UI). Employees are matched by `card_no`, `employee_number`, `tc_identity_no` or `employee_id`. Unmatched entries are returned in `unmatched`. `standard_daily_hours` (default 8) is the overtime baseline. Supports `Idempotency-Key`. Triggers the `attendance.recorded` webhook on success.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
punches | array | No | Punch mode: [{ card_no|employee_id|employee_number|tc_identity_no, timestamp (ISO8601), direction? (IN/OUT), device_id? }] |
records | array | No | Daily mode: [{ card_no|employee_id|..., date (YYYY-MM-DD), status_code, work_hours?, overtime_hours?, note? }] |
standard_daily_hours | number | No | Overtime baseline (default 8) |
curl -X POST "https://api.parsekpro.com/api/external/v1/attendance" \
-H "X-API-Key: pk_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"standard_daily_hours":8,"punches":[{"card_no":"CARD-001","timestamp":"2026-02-10T05:00:00Z","direction":"IN","device_id":"GATE-1"},{"card_no":"CARD-001","timestamp":"2026-02-10T14:30:00Z","direction":"OUT","device_id":"GATE-1"}]}'
const res = await fetch("https://api.parsekpro.com/api/external/v1/attendance", {
method: "POST",
headers: {
'X-API-Key': 'pk_xxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"standard_daily_hours": 8,
"punches": [
{
"card_no": "CARD-001",
"timestamp": "2026-02-10T05:00:00Z",
"direction": "IN",
"device_id": "GATE-1"
},
{
"card_no": "CARD-001",
"timestamp": "2026-02-10T14:30:00Z",
"direction": "OUT",
"device_id": "GATE-1"
}
]
})
});
const data = await res.json();
import requests
resp = requests.post(
"https://api.parsekpro.com/api/external/v1/attendance",
headers={ "X-API-Key": "pk_xxxxxxxx" },
json={
"standard_daily_hours": 8,
"punches": [
{
"card_no": "CARD-001",
"timestamp": "2026-02-10T05:00:00Z",
"direction": "IN",
"device_id": "GATE-1"
},
{
"card_no": "CARD-001",
"timestamp": "2026-02-10T14:30:00Z",
"direction": "OUT",
"device_id": "GATE-1"
}
]
}
)
print(resp.json())
{
"mode": "punch",
"punches_received": 2,
"punches_inserted": 2,
"punches_skipped_duplicate": 0,
"attendance_upserted": 1,
"unmatched": []
}Webhooks
/api/external/v1/webhooks
X-API-Key
scope: webhooks:manage
List webhook endpoints
Returns the company webhook endpoints and the subscribable event catalog (`available_events`).
curl -X GET "https://api.parsekpro.com/api/external/v1/webhooks" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/webhooks", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/webhooks",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"data": [
{
"id": "uuid",
"url": "https://ornek.com/webhook",
"events": [
"invoice.status_changed",
"payment.received"
],
"is_active": true,
"secret_masked": "whsec_…a1b2"
}
],
"available_events": [
"current_account.created",
"current_account.updated",
"inventory.movement.created",
"inventory.low_stock",
"invoice.status_changed",
"payment.received",
"attendance.recorded",
"webhook.test"
]
}/api/external/v1/webhooks/{id}
X-API-Key
scope: webhooks:manage
Webhook detail
Returns a single webhook endpoint detail (secret masked).
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
id | string (uuid) | path | Yes | Webhook ID |
curl -X GET "https://api.parsekpro.com/api/external/v1/webhooks/{id}" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/webhooks/{id}", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/webhooks/{id}",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"id": "uuid",
"url": "https://ornek.com/webhook",
"events": [
"payment.received"
],
"is_active": true,
"secret_masked": "whsec_…a1b2"
}/api/external/v1/webhooks
X-API-Key
scope: webhooks:manage
Create webhook
Adds a new webhook endpoint. Only public `https://` URLs are accepted (private/internal IPs are rejected by SSRF protection). The `secret` is returned in full ONLY once at creation — store it for HMAC-SHA256 signature verification.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
url | string (https) | Yes | Delivery URL (https only) |
events | array | Yes | Event(s) to subscribe |
description | string | No | Description |
curl -X POST "https://api.parsekpro.com/api/external/v1/webhooks" \
-H "X-API-Key: pk_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"url":"https://ornek.com/parsek-webhook","events":["invoice.status_changed","payment.received"],"description":"Muhasebe entegrasyonu"}'
const res = await fetch("https://api.parsekpro.com/api/external/v1/webhooks", {
method: "POST",
headers: {
'X-API-Key': 'pk_xxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"url": "https://ornek.com/parsek-webhook",
"events": [
"invoice.status_changed",
"payment.received"
],
"description": "Muhasebe entegrasyonu"
})
});
const data = await res.json();
import requests
resp = requests.post(
"https://api.parsekpro.com/api/external/v1/webhooks",
headers={ "X-API-Key": "pk_xxxxxxxx" },
json={
"url": "https://ornek.com/parsek-webhook",
"events": [
"invoice.status_changed",
"payment.received"
],
"description": "Muhasebe entegrasyonu"
}
)
print(resp.json())
{
"id": "uuid",
"url": "https://ornek.com/parsek-webhook",
"events": [
"invoice.status_changed",
"payment.received"
],
"is_active": true,
"secret": "whsec_9f1c2b7e...(yalnizca burada tam doner)"
}/api/external/v1/webhooks/{id}
X-API-Key
scope: webhooks:manage
Update webhook
Updates URL, event list, `is_active` (enable/disable) or description. SSRF check is re-applied if the URL changes.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
id | string (uuid) | path | Yes | Webhook ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
url | string (https) | No | New URL |
events | array | No | New event list |
is_active | boolean | No | Enable/disable |
description | string | No | Description |
curl -X PUT "https://api.parsekpro.com/api/external/v1/webhooks/{id}" \
-H "X-API-Key: pk_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"is_active":false}'
const res = await fetch("https://api.parsekpro.com/api/external/v1/webhooks/{id}", {
method: "PUT",
headers: {
'X-API-Key': 'pk_xxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"is_active": false
})
});
const data = await res.json();
import requests
resp = requests.put(
"https://api.parsekpro.com/api/external/v1/webhooks/{id}",
headers={ "X-API-Key": "pk_xxxxxxxx" },
json={
"is_active": False
}
)
print(resp.json())
{
"id": "uuid",
"url": "https://ornek.com/parsek-webhook",
"events": [
"payment.received"
],
"is_active": false
}/api/external/v1/webhooks/{id}
X-API-Key
scope: webhooks:manage
Delete webhook
Deletes the webhook endpoint and its delivery records.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
id | string (uuid) | path | Yes | Webhook ID |
curl -X DELETE "https://api.parsekpro.com/api/external/v1/webhooks/{id}" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/webhooks/{id}", {
method: "DELETE",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.delete(
"https://api.parsekpro.com/api/external/v1/webhooks/{id}",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"success": true
}/api/external/v1/webhooks/{id}/test
X-API-Key
scope: webhooks:manage
Send test delivery
Sends a `webhook.test` event synchronously and returns the result (HTTP code, attempts).
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
id | string (uuid) | path | Yes | Webhook ID |
curl -X POST "https://api.parsekpro.com/api/external/v1/webhooks/{id}/test" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/webhooks/{id}/test", {
method: "POST",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.post(
"https://api.parsekpro.com/api/external/v1/webhooks/{id}/test",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"delivered": true,
"response_code": 200,
"error": null,
"attempts": 1
}/api/external/v1/webhooks/{id}/deliveries
X-API-Key
scope: webhooks:manage
List delivery logs
Returns delivery attempts for the endpoint (status, attempts, HTTP code, error) with pagination. For debugging.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
id | string (uuid) | path | Yes | Webhook ID |
page | integer | query | No | Page (0-based) |
limit | integer | query | No | Page size |
curl -X GET "https://api.parsekpro.com/api/external/v1/webhooks/{id}/deliveries" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/webhooks/{id}/deliveries", {
method: "GET",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/v1/webhooks/{id}/deliveries",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"data": [
{
"id": "uuid",
"event": "payment.received",
"status": "success",
"attempts": 1,
"response_code": 200,
"error": null,
"created_at": "2026-02-10T10:00:00Z"
}
],
"total": 12,
"page": 0,
"limit": 20
}/api/external/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver
X-API-Key
scope: webhooks:manage
Redeliver a delivery
Manually re-sends a failed (or any) delivery, resetting the attempt counter; returns the result synchronously.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
id | string (uuid) | path | Yes | Webhook ID |
deliveryId | string (uuid) | path | Yes | Delivery ID |
curl -X POST "https://api.parsekpro.com/api/external/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver" \
-H "X-API-Key: pk_xxxxxxxx"
const res = await fetch("https://api.parsekpro.com/api/external/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver", {
method: "POST",
headers: {
'X-API-Key': 'pk_xxxxxxxx'
}
});
const data = await res.json();
import requests
resp = requests.post(
"https://api.parsekpro.com/api/external/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver",
headers={ "X-API-Key": "pk_xxxxxxxx" }
)
print(resp.json())
{
"delivered": true,
"response_code": 200,
"error": null,
"attempts": 1,
"will_retry": false
}API Keys
/api/external/keys
Bearer
List API keys
Lists company API keys (admin/super_admin). Keys are returned masked.
curl -X GET "https://api.parsekpro.com/api/external/keys" \
-H "Authorization: Bearer <TOKEN>"
const res = await fetch("https://api.parsekpro.com/api/external/keys", {
method: "GET",
headers: {
'Authorization': 'Bearer <TOKEN>'
}
});
const data = await res.json();
import requests
resp = requests.get(
"https://api.parsekpro.com/api/external/keys",
headers={ "Authorization": "Bearer <TOKEN>" }
)
print(resp.json())
[
{
"id": "uuid",
"key_name": "Muhasebe Entegrasyonu",
"api_key_masked": "...a1b2c3d4",
"is_active": true,
"rate_limit": 60,
"request_count": 128
}
]/api/external/keys
Bearer
Create API key
Generates a new API key (pk_ prefixed). The full key is shown only once at creation.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
key_name | string | No | Key name |
permissions | array | No | Permissions (default ['einvoice']) |
rate_limit | integer | No | Per-minute limit (default 60) |
allowed_domains | array | No | Allowed origins (for browser calls) |
curl -X POST "https://api.parsekpro.com/api/external/keys" \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d '{"key_name":"Muhasebe Entegrasyonu","permissions":["einvoice"],"rate_limit":60}'
const res = await fetch("https://api.parsekpro.com/api/external/keys", {
method: "POST",
headers: {
'Authorization': 'Bearer <TOKEN>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"key_name": "Muhasebe Entegrasyonu",
"permissions": [
"einvoice"
],
"rate_limit": 60
})
});
const data = await res.json();
import requests
resp = requests.post(
"https://api.parsekpro.com/api/external/keys",
headers={ "Authorization": "Bearer <TOKEN>" },
json={
"key_name": "Muhasebe Entegrasyonu",
"permissions": [
"einvoice"
],
"rate_limit": 60
}
)
print(resp.json())
{
"id": "uuid",
"api_key": "pk_9f...c3",
"message": "API anahtari olusturuldu. Bu anahtari guvenli bir yerde saklayin."
}/api/external/keys/{id}
Bearer
Delete API key
Deletes the given API key.
Parameters
| Field | Type | in | Required | Description |
|---|---|---|---|---|
id | string (uuid) | path | Yes | Key ID |
curl -X DELETE "https://api.parsekpro.com/api/external/keys/{id}" \
-H "Authorization: Bearer <TOKEN>"
const res = await fetch("https://api.parsekpro.com/api/external/keys/{id}", {
method: "DELETE",
headers: {
'Authorization': 'Bearer <TOKEN>'
}
});
const data = await res.json();
import requests
resp = requests.delete(
"https://api.parsekpro.com/api/external/keys/{id}",
headers={ "Authorization": "Bearer <TOKEN>" }
)
print(resp.json())
{
"success": true
}Webhooks Active
Parsek sends outbound POST requests to your HTTPS endpoint when subscribed events occur. Manage endpoints via the Webhooks API above.
Event catalog
| Event | Description |
|---|---|
current_account.created | A current account (cari) was created |
current_account.updated | A current account was updated |
inventory.movement.created | A stock movement was recorded |
inventory.low_stock | Stock fell below the minimum level |
invoice.status_changed | An e-Invoice status changed |
payment.received | A payment was received (PayTR) |
webhook.test | Test delivery (manual) |
Delivery headers
| Header | Description |
|---|---|
X-Parsek-Event | Event name |
X-Parsek-Delivery | Unique delivery ID |
X-Parsek-Timestamp | Unix timestamp (seconds) |
X-Parsek-Signature | t=<timestamp>,v1=<hmac_sha256> |
Payload shape
{
"id": "3f1c...",
"event": "payment.received",
"created": "2026-02-10T10:00:00.000Z",
"data": {
"merchant_oid": "SUB123",
"amount": 649,
"currency": "TL",
"request_type": "subscription",
"received_at": "2026-02-10T10:00:00.000Z"
}
}
Signature verification (HMAC-SHA256)
const crypto = require('crypto');
// Express: gövdeyi HAM alın → express.raw({ type: 'application/json' })
function verifyParsekWebhook(req, secret) {
const header = req.headers['x-parsek-signature'] || ''; // 't=...,v1=...'
const parts = Object.fromEntries(header.split(',').map(p => p.split('=')));
const timestamp = parts.t, received = parts.v1;
const body = req.body.toString('utf8'); // ham JSON string
const expected = crypto.createHmac('sha256', secret)
.update(timestamp + '.' + body).digest('hex');
const ok = received && received.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
// Replay koruması: 5 dakikadan eski istekleri reddedin
const fresh = Math.abs(Date.now()/1000 - Number(timestamp)) < 300;
return ok && fresh;
}
Retry & reliability
Failed deliveries (non-2xx or timeout) are retried automatically 4 times with backoff (30s, 2m, 10m, 30m). You can inspect attempts via the deliveries endpoint and re-send manually via the redeliver endpoint. Only public https URLs are accepted (private/internal IPs are blocked — SSRF protection).
Coming Soon Soon
The APIs below are under development and not live yet. Only the “Active” endpoints above are usable.
ERP Data API
Read-only access to projects and progress payments.
OHS / IBYS API
Employee health tracking, PPE assignment and IBYS notification integration.
OIZ API
Participant companies, parcels, dues accruals and utility meter data.