Genel bakış
API, firmanızın kendi kayıtlarına iki yönlü erişim sağlar: paneldeki tüm modüllerin kayıtlarını listeleyebilir, ekleyebilir, güncelleyebilir, silebilir; durum değiştirme ve tahsilat gibi işlemleri yapabilirsiniz. API ile yapılan değişiklikler aynı anda panelde ve tüm cihazlarda görünür; panelde yapılan değişiklikleri de değişiklik akışıyla kendi sisteminize alırsınız.
| Adres | https://kurumsalhesap.com/api/v1 |
| Biçim | JSON, UTF-8 |
| Bağlantı | Yalnızca HTTPS |
| Kimlik | X-Company-Code + X-Api-Secret |
| Şart | Firmanın etkin bir lisansı olmalı |
| İstek sınırı | Anahtar başına dakikada 120 |
Başlarken
- Firmanızın etkin bir lisansı olmalı. API tüm lisanslarda, ücretsiz başlangıç lisansında da açıktır; lisans sona erince istekler 402 ile reddedilir.
- Firma yöneticisi Ayarlar → API Erişimi bölümünden bir anahtar oluşturur: ad, erişim türü (okuma ve yazma ya da yalnızca okuma), işlem kullanıcısı ve isteğe bağlı IP kısıtı seçilir.
- Gizli anahtar yalnızca oluşturulduğu anda gösterilir; güvenli bir yere kaydedin. Firma kodunuz aynı ekranda yazar.
- İlk isteği gönderin; yanıtta firmanız, anahtarınız ve lisansınız görünür.
curl https://kurumsalhesap.com/api/v1/me \
-H "X-Company-Code: FIRMA_KODUNUZ" \
-H "X-Api-Secret: khs_GIZLI_ANAHTARINIZ"Kimlik doğrulama
Her istekte iki başlık zorunludur. Anahtar tek bir firmaya aittir; firma kodu ile gizli anahtar birlikte eşleşmezse istek reddedilir.
| Başlık | Zorunlu | Açıklama |
|---|---|---|
X-Company-Code | Evet | Firma kodunuz (Ayarlar → API Erişimi) |
X-Api-Secret | Evet | khs_ ile başlayan gizli anahtar |
Content-Type | Gövdeli isteklerde | application/json (dosya yüklemede multipart/form-data da olur) |
Accept-Language | Hayır | Mesaj dili: tr, en… (varsayılan tr) |
Idempotency-Key | Hayır | Yazma isteklerini güvenle tekrarlamak için benzersiz değer |
İstekler anahtarın işlem kullanıcısı adına çalışır: kayıtlarda ekleyen ve güncelleyen olarak o kullanıcı görünür, onun yetkileri geçerlidir. Örneğin kullanıcı yönetimi yalnızca yönetici işlem kullanıcısıyla yapılabilir; kişisel dosya ve notlardan yalnızca o kullanıcınınkiler görünür.
Güvenlik
- Gizli anahtarı tarayıcıda çalışan koda ya da mobil uygulamaya koymayın; API'yi yalnızca kendi sunucunuzdan çağırın.
- Anahtarı kaynak kod deposuna yazmayın; ortam değişkeninde ya da gizli anahtar kasasında saklayın.
- Yalnızca okuyan entegrasyonlar için Yalnızca Okuma anahtarı, sabit IP'li sunucular için IP kısıtı kullanın.
- Anahtarın ele geçtiğinden şüphelenirseniz Ayarlar → API Erişimi bölümünden hemen iptal edip yenisini oluşturun.
- Aynı IP adresinden 10 dakikada 20 hatalı kimlik denemesi yapılırsa istekler geçici olarak durdurulur.
Örnek kodlar
Örnekler ek kütüphane gerektirmez: PHP 8 (cURL), C# (.NET 6+ HttpClient), Java 11+ (java.net.http). Firma kodunu ve gizli anahtarı ortam değişkenlerinden (KH_COMPANY_CODE, KH_API_SECRET) okur. Dil seçiminiz sayfadaki tüm örneklere uygulanır.
<?php
// Kurumsal Hesap REST API — PHP 8+ (cURL, ek kütüphane gerekmez)
const KH_BASE = 'https://kurumsalhesap.com/api/v1';
function kh(string $method, string $path, ?array $body = null): array
{
$headers = [
'X-Company-Code: ' . getenv('KH_COMPANY_CODE'), // firma kodunuz
'X-Api-Secret: ' . getenv('KH_API_SECRET'), // khs_ ile başlayan gizli anahtar
'Accept: application/json',
];
$ch = curl_init(KH_BASE . $path);
if ($body !== null) {
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body, JSON_UNESCAPED_UNICODE));
}
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
]);
$raw = curl_exec($ch);
$http = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
$json = json_decode((string) $raw, true);
if ($raw === false || $http >= 400 || empty($json['status'])) {
throw new RuntimeException(($json['message'] ?? curl_error($ch)) . " (HTTP $http)");
}
return $json;
}
// 1) Carileri listele (sayfa başına en fazla 500)
$page = kh('GET', '/customers?per_page=100&page=1');
foreach ($page['data'] as $customer) {
echo $customer['id'], ' - ', $customer['title'], PHP_EOL;
}
// 2) Yeni cari ekle
$customer = kh('POST', '/customers', [
'title' => 'Örnek Teknoloji Ltd. Şti.',
'mail' => '[email protected]',
'phone' => '0212 000 00 00',
])['data'];
// 3) Yalnızca telefonu güncelle (gönderilmeyen alanlar korunur)
kh('PATCH', '/customers/' . $customer['id'], ['phone' => '0212 111 11 11']);
// 4) Teklif oluştur (ürün numaraları: GET /products)
$offer = kh('POST', '/offers', [
'customer_id' => $customer['id'],
'date' => date('Y-m-d'),
'product_list' => [
['product_id' => 12, 'amount' => 2, 'price' => 1500, 'description' => 'Yıllık lisans'],
],
])['data'];
echo 'Teklif no: ', $offer['code'], PHP_EOL;// Kurumsal Hesap REST API — C# (.NET 6+), ek paket gerekmez
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json.Nodes;
var api = new KurumsalHesapClient(
Environment.GetEnvironmentVariable("KH_COMPANY_CODE")!, // firma kodunuz
Environment.GetEnvironmentVariable("KH_API_SECRET")!); // khs_ ile başlayan gizli anahtar
// 1) Carileri listele (sayfa başına en fazla 500)
var page = await api.SendAsync(HttpMethod.Get, "customers?per_page=100&page=1");
foreach (var customer in page["data"]!.AsArray())
Console.WriteLine($"{customer!["id"]} - {customer["title"]}");
// 2) Yeni cari ekle
var created = await api.SendAsync(HttpMethod.Post, "customers", new
{
title = "Örnek Teknoloji Ltd. Şti.",
mail = "[email protected]",
phone = "0212 000 00 00",
});
var customerId = (int)created["data"]!["id"]!;
// 3) Yalnızca telefonu güncelle (gönderilmeyen alanlar korunur)
await api.SendAsync(HttpMethod.Patch, $"customers/{customerId}", new { phone = "0212 111 11 11" });
// 4) Teklif oluştur (ürün numaraları: GET /products)
var offer = await api.SendAsync(HttpMethod.Post, "offers", new
{
customer_id = customerId,
date = DateTime.Today.ToString("yyyy-MM-dd"),
product_list = new[] { new { product_id = 12, amount = 2, price = 1500m, description = "Yıllık lisans" } },
});
Console.WriteLine($"Teklif no: {offer["data"]!["code"]}");
public sealed class KurumsalHesapClient
{
private readonly HttpClient _http;
public KurumsalHesapClient(string companyCode, string apiSecret, string baseUrl = "https://kurumsalhesap.com/api/v1/")
{
_http = new HttpClient { BaseAddress = new Uri(baseUrl), Timeout = TimeSpan.FromSeconds(60) };
_http.DefaultRequestHeaders.Add("X-Company-Code", companyCode);
_http.DefaultRequestHeaders.Add("X-Api-Secret", apiSecret);
_http.DefaultRequestHeaders.Add("Accept", "application/json");
}
public async Task<JsonNode> SendAsync(HttpMethod method, string path, object? body = null)
{
using var request = new HttpRequestMessage(method, path);
if (body != null) request.Content = JsonContent.Create(body);
using var response = await _http.SendAsync(request);
var json = JsonNode.Parse(await response.Content.ReadAsStringAsync())!;
if (!response.IsSuccessStatusCode || json["status"]?.GetValue<bool>() != true)
throw new HttpRequestException($"{json["message"]} (HTTP {(int)response.StatusCode})");
return json;
}
}// Kurumsal Hesap REST API — Java 11+ (java.net.http), ek kütüphane gerekmez
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class KurumsalHesapClient {
private static final String BASE_URL = "https://kurumsalhesap.com/api/v1/";
private final HttpClient http = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(20)).build();
private final String companyCode;
private final String apiSecret;
public KurumsalHesapClient(String companyCode, String apiSecret) {
this.companyCode = companyCode;
this.apiSecret = apiSecret;
}
/** İsteği gönderir, JSON yanıtı metin olarak döndürür; 4xx / 5xx yanıtta hata fırlatır. */
public String send(String method, String path, String json) throws Exception {
HttpRequest.Builder request = HttpRequest.newBuilder(URI.create(BASE_URL + path))
.timeout(Duration.ofSeconds(60))
.header("X-Company-Code", companyCode)
.header("X-Api-Secret", apiSecret)
.header("Accept", "application/json");
if (json != null) {
request.header("Content-Type", "application/json; charset=utf-8")
.method(method, HttpRequest.BodyPublishers.ofString(json));
} else {
request.method(method, HttpRequest.BodyPublishers.noBody());
}
HttpResponse<String> response = http.send(request.build(), HttpResponse.BodyHandlers.ofString());
if (response.statusCode() >= 400) {
throw new IllegalStateException("HTTP " + response.statusCode() + ": " + response.body());
}
return response.body();
}
public static void main(String[] args) throws Exception {
KurumsalHesapClient api = new KurumsalHesapClient(
System.getenv("KH_COMPANY_CODE"), // firma kodunuz
System.getenv("KH_API_SECRET")); // khs_ ile başlayan gizli anahtar
// 1) Carileri listele (JSON'u Jackson ya da Gson ile nesneye çevirebilirsiniz)
System.out.println(api.send("GET", "customers?per_page=100&page=1", null));
// 2) Yeni cari ekle — yanıttaki data.id yeni kaydın numarasıdır
String created = api.send("POST", "customers",
"{\"title\":\"Örnek Teknoloji Ltd. Şti.\",\"mail\":\"[email protected]\",\"phone\":\"0212 000 00 00\"}");
System.out.println(created);
// 3) Yalnızca telefonu güncelle (gönderilmeyen alanlar korunur)
api.send("PATCH", "customers/1520", "{\"phone\":\"0212 111 11 11\"}");
// 4) Teklif oluştur (ürün numaraları: GET /products)
api.send("POST", "offers",
"{\"customer_id\":1520,\"date\":\"2026-09-15\","
+ "\"product_list\":[{\"product_id\":12,\"amount\":2,\"price\":1500,\"description\":\"Yıllık lisans\"}]}");
}
}Yanıt biçimi ve hatalar
Tüm yanıtlar JSON'dur. Başarılı yanıtta status true olur ve kayıt data alanındadır:
{
"status": true,
"message": "Cari kaydı eklendi.",
"data": {
"id": 1520,
"code": "C00148",
"title": "Örnek Teknoloji Ltd. Şti.",
"phone": "0212 000 00 00",
"update_date": "2026-09-15 10:42:07"
}
}Yazma işlemlerinde related, işlemden etkilenen diğer kayıtların güncel halini; removed ise işlemle kaldırılan kayıtların numaralarını taşır (ör. { "agenda": [41] }). Kendi tarafınızda kopya tutuyorsanız bunları da uygulayın.
Hatalı yanıtta status false olur; message kullanıcıya gösterilebilecek açıklama, error ise programınızın kontrol edebileceği sabit koddur:
{
"status": false,
"message": "Cari ünvanını girmelisiniz!",
"error": "validation_failed"
}| HTTP | error | Anlamı |
|---|---|---|
| 200 / 201 | — | Başarılı (201: yeni kayıt oluşturuldu) |
| 400 | bad_request, invalid_json | Parametre ya da JSON gövde hatalı |
| 401 | auth_missing, auth_invalid | Başlık eksik ya da firma kodu / gizli anahtar hatalı |
| 402 | license_required | Firmanın etkin lisansı yok |
| 403 | read_only_key, ip_not_allowed, user_inactive, company_suspended | Yetki ya da erişim kısıtı |
| 404 | not_found, unknown_resource, unknown_action | Kayıt, kaynak ya da işlem bulunamadı |
| 405 | method_not_allowed | Kaynak bu işlemi desteklemiyor |
| 410 | cursor_expired | Değişiklik imleci geçersiz; kayıtları yeniden listeleyin |
| 422 | validation_failed | İş kuralı reddetti (zorunlu alan, geçersiz durum vb.) |
| 429 | rate_limited, too_many_failures | İstek sınırı aşıldı; Retry-After kadar bekleyin |
| 500 | server_error | Sunucu hatası; kısa süre sonra tekrar deneyin |
İstek sınırı
Her anahtar dakikada 120 istek yapabilir. Yanıtlardaki X-RateLimit-Limit ve X-RateLimit-Remaining başlıkları kalan hakkınızı gösterir. Sınır aşılırsa 429 döner; Retry-After başlığındaki saniye kadar bekleyip tekrar deneyin. Toplu aktarımlarda sayfa başına 500 kayıt listeleyerek istek sayısını azaltın.
Kaynaklar ve uçlar
Tüm adresler API adresine eklenir. Kaynak adları adreste kullanılır; güncel liste GET /resources ile de alınabilir.
| Yöntem | Adres | Açıklama |
|---|---|---|
| GET | /{kaynak} | Listeleme (sayfalı, filtrelenebilir) |
| GET | /{kaynak}/{id} | Tek kayıt |
| POST | /{kaynak} | Yeni kayıt |
| PATCH | /{kaynak}/{id} | Güncelleme; yalnızca gönderilen alanlar değişir (PUT de aynı çalışır) |
| DELETE | /{kaynak}/{id} | Silme |
| POST | /{kaynak}/{id}/{işlem} | Özel işlem: durum değiştirme, tahsilat, tamamlama… |
| GET | /changes | Değişiklik akışı |
| GET | /me | Firma, anahtar, lisans ve istek sınırı bilgisi |
| GET | /resources | Kaynakların ve işlemlerinin listesi |
| GET | /definitions | Sistem tanımları: para birimi, birim, ülke / il / ilçe, teklif durumları, bankalar… |
| Kaynak | Modül | İşlemler |
|---|---|---|
customers |
Cariler | Oku · Ekle · Güncelle · Sil delete_image, portal_link, portal_disable |
customer_prices |
Cariye Özel Fiyatlar | Oku · Ekle · Güncelle · Sil |
offers |
Teklifler | Oku · Ekle · Güncelle · Sil change_status, pdf |
operations |
İşler & Projeler | Oku · Ekle · Güncelle · Sil change_status, to_assets, pdf |
contracts |
Sözleşmeler | Oku · Ekle · Güncelle · Sil change_status, pdf |
contract_templates |
Sözleşme Şablonları | Oku · Ekle · Güncelle · Sil |
products |
Ürün & Hizmetler | Oku · Ekle · Güncelle · Sil |
product_categories |
Ürün Kategorileri | Oku · Ekle · Güncelle · Sil |
costs |
Maliyetler | Oku · Ekle · Güncelle · Sil |
cost_categories |
Maliyet Kategorileri | Oku · Ekle · Güncelle · Sil |
assets |
Ürün & Hizmet Takibi | Oku · Ekle · Güncelle · Sil |
asset_events |
Takip Hareketleri | Oku · Ekle · Güncelle · Sil |
finances |
Gelir & Gider | Oku · Ekle · Güncelle · Sil pay |
accounting_invoices |
Fatura Aktarımı | Oku · Ekle · Güncelle · Sil |
accounts |
Kasa & Banka Hesapları | Oku · Ekle · Güncelle · Sil |
agenda |
Ajanda | Oku · Ekle · Güncelle · Sil toggle |
documents |
Dokümanlar | Oku · Ekle · Güncelle · Sil upload, download |
notes |
Notlar | Oku · Ekle · Güncelle · Sil |
users |
Kullanıcılar | Oku · Ekle · Güncelle · Sil |
op_statuses |
İş Durumları | Oku · Ekle · Güncelle · Sil order |
addresses |
Adresler | Oku · Ekle · Güncelle · Sil |
banks |
Banka Hesapları | Oku · Ekle · Güncelle · Sil |
partner |
Firma Bilgileri | Oku · Güncelle logo_delete |
Listeleme ve filtreleme
| Parametre | Açıklama |
|---|---|
page | Sayfa numarası (varsayılan 1) |
per_page | Sayfa başına kayıt, en fazla 500 (varsayılan 100) |
ids | Virgülle ayrılmış kayıt numaraları: ids=12,15,18 |
updated_since | Bu tarihten sonra eklenen ya da güncellenen kayıtlar: updated_since=2026-09-01 08:30:00 |
filter[alan] | Alan eşitliği: filter[customer_id]=15, filter[status]=1 |
Yanıttaki meta alanı sayfalama bilgisini ve değişiklik akışının o anki imlecini (cursor) taşır:
"meta": { "page": 1, "per_page": 100, "total": 248, "last_page": 3, "cursor": 90412 }Liste satırları paneldeki satırlarla aynıdır: kayıt alanlarının yanında görüntü için hazırlanmış alanlar da bulunur (ör. customer_title, status_name, count_offer). Silinen kayıtlar listelenmez.
Ekleme, güncelleme ve silme
Yeni kayıt için alanları JSON olarak POST edin; kaydın oluşan hali 201 ile döner. Kod gibi alanlar boş bırakılırsa panelde olduğu gibi otomatik verilir.
Güncellemede yalnızca değiştirmek istediğiniz alanları gönderin; gönderilmeyen alanlar olduğu gibi kalır. Kalem listeleri (product_list, cost_list, lines) gönderilirse listenin tamamının yerine geçer.
Silme, kaydı paneldeki gibi kaldırır; etkilenen bağlı kayıtlar yanıtın related ve removed alanlarında bildirilir.
İş kuralları paneldekiyle aynıdır: örneğin onaylanmış sözleşme değiştirilemez, tahsilatı olan faturanın para birimi değiştirilemez, dosya yüklemede firmanızın dosya alanı kotası uygulanır. Kural reddederse 422 ve açıklayıcı bir mesaj döner.
Tekrarlanan istekler
Ağ kesintisinde bir yazma isteğini güvenle tekrarlamak için Idempotency-Key başlığına benzersiz bir değer (ör. kendi kayıt numaranız ya da bir UUID, 8-60 karakter) koyun. Aynı değerle gelen sonraki istek işlemi yeniden yapmaz; ilk başarılı yanıtı Idempotent-Replayed: true başlığıyla döndürür. Sonuçlar 30 gün saklanır.
Alan rehberi
Yazma işlemlerinde kabul edilen alanlar; kalın olanlar zorunludur. Tanım numaraları (para birimi, birim, ülke, il, ilçe, teklif durumu, banka) GET /definitions yanıtından, iş durumları GET /op_statuses listesinden alınır. Tarihler YYYY-AA-GG, tarih-saatler YYYY-AA-GG SS:DD:ss biçimindedir; tutarlarda ondalık ayırıcı olarak nokta kullanın.
customers
title · code · type_id · category_id · name · surname · ident_number · tax_number · tax_office · iban · mail · phone · country_id · city_id · district_id · address · color · description · status · logo
code boş bırakılırsa otomatik verilir. logo: data:image/png;base64,… biçiminde resim. portal_link { regenerate } cari ekranı bağlantısını üretir, portal_disable { enabled } kapatır ya da açar.
customer_prices
customer_id · product_id · price
Carinin tekliflerinde kullanılan özel ürün fiyatı.
offers
customer_id · date · miad_date · description · price · price_type · product_list · cost_list
product_list: [{ product_id, amount, price, description }], cost_list: [{ cost_id, amount, price, description }]. price_type para birimi numarasıdır (boşsa firma para birimi); price boşsa kalemlerden hesaplanır. change_status { state, status_text }: state 1 onaylandı, 2 iletildi (teklif PDF olarak carinin e-posta adresine gönderilir), 3 reddedildi; tüm durumlar GET /definitions → offer_statuses. Satırda kalemler json_product_list / json_cost_list olarak döner.
operations
customer_id · title · date · offer_id · status · miad_date · description · price · price_type · product_list · cost_list
status ve change_status { state, status_text } değerleri firmanızın iş durumlarının (op_statuses) numaralarıdır. to_assets { all } işin kalemlerini Ürün & Hizmet Takibi kayıtlarına aktarır.
contracts
title · content · customer_id · date · start_date · end_date · renewal_months · reminder_days · price · currency_id · template_id · product_id · offer_id · operation_id · item_type
content HTML (p, strong, ul, table…) ve {{değişken}} içerebilir. change_status { state, status_text }: 1 taslak, 2 onay bekliyor, 3 onaylandı, 4 reddedildi, 5 iptal. Onaylanmış ya da iptal edilmiş sözleşme değiştirilemez.
contract_templates
title · content · product_id · item_type · status
products
name · category_id · code · status · types · currency_id · price · unit_id · description · period · maintenance_period · warranty_months
types: product, service, licence, device değerlerinden biri ya da birkaçı (dizi ya da virgülle). period, maintenance_period ve warranty_months ay cinsindendir; unit_id için GET /definitions → units.
product_categories
name · track_licence · track_maintenance · track_warranty · licence_period · maintenance_period · warranty_months
costs
name · category_id · code · status · currency_id · unit_id · price · description
cost_categories
name
assets
name · customer_id · product_id · operation_id · direction · types · code · brand · model · serial_no · licence_key · quantity · start_date · end_date · billing_period · price · cost_price · currency_id · auto_renew · warranty_end · maintenance_period · last_maintenance · next_maintenance · maintenance_price · reminder_days · status · description
direction: 1 satılan (müşteriye), 2 alınan (tedarikçiden). billing_period ay cinsindendir (0 tek seferlik, 1, 3, 6, 12, 24).
asset_events
asset_id · date · type · next_date · price · currency_id · description
finances
kind · direction · date · amount · currency_id · customer_id · operation_id · offer_id · asset_id · account_id · method · ref_id · due_date · recurring · title · doc_no · description
kind: 1 fatura, 2 tahsilat / ödeme. direction: 1 gelir / tahsilat, 2 gider / ödeme. method: 1 nakit, 2 havale / EFT, 3 kredi kartı, 4 çek, 5 senet, 6 diğer. ref_id tahsilat ya da ödemenin kapattığı faturadır. Faturaya ödeme: POST /finances/{id}/pay { amount, date, account_id, method, description }.
accounting_invoices
type · customer_id · date · due_date · currency_id · exchange_rate · vat_included · lines · finance_id · operation_id · offer_id · create_finance · doc_no · description
Muhasebe programına gönderim ve e-belge işlemleri panelden yapılır. Satırda kalemler json_lines olarak döner.
accounts
name · type · bank_id · iban · currency_id · opening_balance · status · description
agenda
title · start_at · end_at · all_day · type · user_id · customer_id · operation_id · asset_id · location · description · status
toggle kaydı tamamlandı olarak işaretler ya da geri alır.
documents
name · description · owner_id · table_name · table_id
POST /documents yalnızca klasör oluşturur; dosya için POST /documents/upload. owner_id üst klasördür; table_name: customer, offer, operation, asset.
notes
title · note · table_name · table_id · remind · remind_at
table_name: customer, offer, operation, asset. remind 1 ise remind_at zamanında ajandaya hatırlatma kurulur, 0 ise kaldırılır; gönderilmezse dokunulmaz.
users
name · surname · email · type_id · status · phone
İşlem kullanıcısı yönetici olmalıdır. type_id ve status değerleri GET /definitions → user_types, user_statuses.
op_statuses
name · short_name · order · color
Sıralama: POST /op_statuses/order { ids: [3, 1, 2] }.
addresses
title · address · mail · phone · maps · about · status · country_id · city_id · district_id · city_name · district_name
banks
bank_id · account_iban · account_name · account_swift
bank_id için GET /definitions → banks.
partner
name · email · phone · tax_number · tax_office · kep · sector_id · currency_id · country_id · city_id · address · about · lang_id · website · subdomain · logo
Yalnızca güncellenir: PATCH /partner/{id} (id = GET /me → company.id).
Değişiklik akışı
Panelde, mobil cihazlarda ya da başka bir entegrasyonda yapılan her değişiklik firmanızın değişiklik akışına sırayla yazılır. Kendi sisteminizi güncel tutmak için kayıtları bir kez listeleyin, sonra yalnızca değişiklikleri çekin:
- GET /changes ile başlangıç imlecini (cursor) alıp saklayın.
- Kaynakları listeleyerek ilk aktarımı yapın.
- Belirli aralıklarla GET /changes?cursor={imleç}&include=rows çağırın: changes sırayla gelen değişiklikleri, rows değişen kayıtların güncel halini, deleted silinen kayıt numaralarını taşır.
- Yanıttaki cursor değerini saklayın; has_more true ise hemen tekrar çağırın (tek yanıtta en fazla 500 değişiklik gelir).
- Değişiklik geçmişi 60 gün saklanır. 410 cursor_expired dönerse (uzun süre çekilmediği için geçmiş temizlenmişse) kaynakları yeniden listeleyip yanıttaki meta.cursor ile devam edin.
{
"status": true,
"message": "",
"data": {
"cursor": 90458,
"has_more": false,
"changes": [
{ "cursor": 90431, "resource": "customers", "id": 1520, "type": "upsert", "user_id": 8, "changed_at": "2026-09-15 10:42:07" },
{ "cursor": 90458, "resource": "agenda", "id": 311, "type": "delete", "user_id": 12, "changed_at": "2026-09-15 10:44:51" }
],
"rows": { "customers": [ { "id": 1520, "title": "Örnek Teknoloji Ltd. Şti." } ] },
"deleted": { "agenda": [311] }
}
}API ile kendi yaptığınız değişiklikler de akışta görünür; changes içindeki user_id işlem kullanıcınızla (GET /me → user.id) aynıysa bunları atlayabilirsiniz.
<?php
// Değişiklik akışı: kendi sisteminizi Kurumsal Hesap ile eşit tutar (yukarıdaki kh() fonksiyonunu kullanır)
// HTTP 410 (cursor_expired) alırsanız imleç dosyasını silip ilk aktarımı yeniden yapın.
$cursorFile = __DIR__ . '/kh-cursor.txt';
if (!is_file($cursorFile)) {
// İlk çalıştırma: önce imleci alın, sonra kayıtları listeleyip aktarın
file_put_contents($cursorFile, kh('GET', '/changes')['data']['cursor']);
// kh('GET', '/customers?per_page=500&page=1') ... ile ilk aktarım
}
do {
$cursor = (int) file_get_contents($cursorFile);
$feed = kh('GET', "/changes?cursor=$cursor&include=rows")['data'];
foreach ($feed['rows'] as $resource => $rows) {
foreach ($rows as $row) {
saveLocal($resource, $row); // kendi veritabanınıza ekleyin / güncelleyin
}
}
foreach ($feed['deleted'] as $resource => $ids) {
foreach ($ids as $id) {
deleteLocal($resource, $id); // kendi veritabanınızdan kaldırın
}
}
file_put_contents($cursorFile, $feed['cursor']);
} while ($feed['has_more']);// Değişiklik akışı: kendi sisteminizi Kurumsal Hesap ile eşit tutar (KurumsalHesapClient yukarıda)
// HTTP 410 (cursor_expired) alırsanız ilk aktarımı yeniden yapıp yeni imleçle devam edin.
// İlk çalıştırmada: (long)(await api.SendAsync(HttpMethod.Get, "changes"))["data"]!["cursor"]!
long cursor = LoadCursor();
bool hasMore;
do
{
var feed = (await api.SendAsync(HttpMethod.Get, $"changes?cursor={cursor}&include=rows"))["data"]!;
foreach (var (resource, rows) in feed["rows"]!.AsObject())
foreach (var row in rows!.AsArray())
SaveLocal(resource, row!); // kendi veritabanınıza ekleyin / güncelleyin
foreach (var (resource, ids) in feed["deleted"]!.AsObject())
foreach (var id in ids!.AsArray())
DeleteLocal(resource, (int)id!); // kendi veritabanınızdan kaldırın
cursor = (long)feed["cursor"]!;
SaveCursor(cursor);
hasMore = (bool)feed["has_more"]!;
} while (hasMore);// Değişiklik akışı (Jackson: com.fasterxml.jackson.core:jackson-databind)
// HTTP 410 (cursor_expired) alırsanız ilk aktarımı yeniden yapıp yeni imleçle devam edin.
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Iterator;
import java.util.Map;
ObjectMapper mapper = new ObjectMapper();
// İlk çalıştırmada: mapper.readTree(api.send("GET", "changes", null)).at("/data/cursor").asLong()
long cursor = loadCursor();
boolean hasMore;
do {
JsonNode feed = mapper.readTree(api.send("GET", "changes?cursor=" + cursor + "&include=rows", null)).get("data");
for (Iterator<Map.Entry<String, JsonNode>> it = feed.get("rows").fields(); it.hasNext(); ) {
Map.Entry<String, JsonNode> entry = it.next();
for (JsonNode row : entry.getValue()) {
saveLocal(entry.getKey(), row); // kendi veritabanınıza ekleyin / güncelleyin
}
}
for (Iterator<Map.Entry<String, JsonNode>> it = feed.get("deleted").fields(); it.hasNext(); ) {
Map.Entry<String, JsonNode> entry = it.next();
for (JsonNode id : entry.getValue()) {
deleteLocal(entry.getKey(), id.asInt()); // kendi veritabanınızdan kaldırın
}
}
cursor = feed.get("cursor").asLong();
saveCursor(cursor);
hasMore = feed.get("has_more").asBoolean();
} while (hasMore);Dosyalar ve PDF
| Yöntem | Adres | Açıklama |
|---|---|---|
| POST | /documents/upload | Dosya yükler. multipart/form-data ile file alanı ya da JSON ile name ve content_base64. İsteğe bağlı: name, owner_id (klasör), table_name + table_id (bağlı kayıt). En fazla 50 MB; firmanızın dosya alanından düşer. |
| GET | /documents/{id}/download | Dosyayı indirir (ikili içerik). |
| GET | /offers/{id}/pdf | Teklif PDF'i |
| GET | /operations/{id}/pdf | İş formu PDF'i |
| GET | /contracts/{id}/pdf | Sözleşme PDF'i |
# Dosya yükleme (multipart) — cariye bağlı, en fazla 50 MB
curl https://kurumsalhesap.com/api/v1/documents/upload \
-H "X-Company-Code: FIRMA_KODUNUZ" -H "X-Api-Secret: khs_GIZLI_ANAHTARINIZ" \
-F "[email protected]" -F "table_name=customer" -F "table_id=1520"
# Dosya indirme
curl -o dosya.pdf https://kurumsalhesap.com/api/v1/documents/3120/download \
-H "X-Company-Code: FIRMA_KODUNUZ" -H "X-Api-Secret: khs_GIZLI_ANAHTARINIZ"
# Teklif PDF'i
curl -o teklif.pdf https://kurumsalhesap.com/api/v1/offers/845/pdf \
-H "X-Company-Code: FIRMA_KODUNUZ" -H "X-Api-Secret: khs_GIZLI_ANAHTARINIZ"Destek
Entegrasyonunuzla ilgili sorularınız için iletişim formunu kullanabilirsiniz. Firma kodunuzu yazmanız yeterli; gizli anahtarınızı hiçbir zaman paylaşmayın.