İçeriğe geç

İşlemde şu anda geliştirme aşamasında. Kayıtlar yakında açılacak.

Geliştiriciler için

İşlemde API

İşlerinizi ve müşterilerinizi kendi yazılımınıza, muhasebe ya da e-ticaret sisteminize bağlayın. Okuyun, iş ve müşteri açın, durum değiştirin, ödeme kaydedin; olup biteni webhook'la anında alın.

Adres
/api/v1
Kimlik
x-api-key
Sınır
Dakikada 600
Paket
İşletme

Başlarken

  1. Panelde Ayarlar → API sayfasından bir anahtar oluşturun. Anahtar yalnızca bir kez gösterilir; güvenli bir yerde saklayın.
  2. Anahtarı sunucunuzda ISLEMDE_API_KEY ortam değişkenine koyun.
  3. Her isteğe x-api-key başlığıyla ekleyin. İlk isteğiniz, teslime hazır işler:
curl "https://islemde.app/api/v1/jobs?status=ready" \
  -H "x-api-key: $ISLEMDE_API_KEY"

Dilinizi bir kez seçin; sayfadaki bütün örnekler o dilde açılır.

Kimlik doğrulama

Anahtarı x-api-key başlığında ya da Authorization: Bearer isl_… olarak gönderin. Anahtarlar isl_ ile başlar ve işletmenin bütün işlerine ve müşterilerine erişir.

Anahtarı tarayıcıda, mobil uygulamada ya da herkese açık bir depoda tutmayın; her zaman kendi sunucunuzdan istek atın. Sızdığını düşünürseniz Ayarlar → API sayfasından iptal edin, o an çalışmayı bırakır.

Okuma ve yazma

Anahtarı oluştururken yetkisini seçersiniz. Yalnızca okuma (varsayılan) anahtarı listeleri ve kayıtları okur, hiçbir şeyi değiştiremez. Okuma ve yazma anahtarı ayrıca iş ve müşteri açar, düzeltir, durum değiştirir, not ekler ve ödeme kaydeder. Yazma yetkisi olmayan bir anahtarla yazmaya çalışırsanız 403 insufficient_scope gelir. Yetkiler sonradan değişmez; gerekirse yeni bir anahtar oluşturun.

Yazmalar paneldekiyle aynı kurallardan geçer: aynı doğrulamalar, işlem hakkı, müşteriye giden SMS ve e-postalar, iş geçmişi ve webhook'lar. Geçmişte yapan olarak anahtarın adı görünür, örn. API · Muhasebe. Hesap salt okunurken (ödeme alınamadı ya da deneme bitti) yazmalar kapalıdır, okuma sürer.

Yazma yetkili bir anahtarla açılan her iş işlem hakkınızdan düşer ve müşteriye SMS gidebilir. Denemelerinizi gerçek müşteri numaralarıyla yapmayın.

Hazır istemci

Aşağıdaki örnekler bu küçük yardımcıyı kullanır: biri tek istek atar ve hatada anlaşılır bir mesajla durur, öbürü bir listenin bütün sayfalarını sırayla getirir. Projenize bir kez ekleyin. JavaScript ve C# için ek paket gerekmez; Python'da requests, PHP'de Guzzle yeterli.

// islemde.js · Node 18 ve üzeri, ek paket gerekmez
const BASE = "https://islemde.app/api/v1";

export async function islemde(path, params = {}) {
  const url = new URL(BASE + path);
  for (const [name, value] of Object.entries(params)) {
    if (value != null) url.searchParams.set(name, value);
  }
  const res = await fetch(url, {
    headers: { "x-api-key": process.env.ISLEMDE_API_KEY },
  });
  const body = await res.json();
  if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
  return body;
}

// Listenin bütün sayfalarını sırayla getirir:
// for await (const job of all("/jobs")) { … }
export async function* all(path, params = {}) {
  let cursor;
  while (cursor !== null) {
    const page = await islemde(path, { ...params, cursor });
    yield* page.data;
    cursor = page.nextCursor;
  }
}

Sayfalama

Liste uçları en fazla limit kayıt (varsayılan 25, en çok 100) ve bir nextCursor döner. Sonraki sayfa için onu cursor olarak gönderin; son sayfada null gelir. Siz okurken yeni iş açılsa da sayfalar kaymaz; aynı kaydı iki kez almazsınız.

Hazır istemciyle döngüyü siz yazmazsınız; kayıtlar tek tek gelir, sayfalar arka planda çekilir:

# İlk sayfa
curl "https://islemde.app/api/v1/jobs?state=all&limit=100" \
  -H "x-api-key: $ISLEMDE_API_KEY"

# Sonraki sayfa: cevaptaki nextCursor ile
curl "https://islemde.app/api/v1/jobs?state=all&limit=100&cursor=1046" \
  -H "x-api-key: $ISLEMDE_API_KEY"

Güvenli tekrar deneme

Ağ koptuğunda isteğin bize ulaşıp ulaşmadığını bilemezsiniz. POST isteklerine her yeni işlem için benzersiz bir Idempotency-Key başlığı ekleyin (örn. bir UUID); tekrar denerken aynı değeri gönderin. 24 saat içinde aynı anahtar ve aynı gövdeyle gelen istek ikinci kez kayıt açmaz, ilk başarılı cevabı idempotent-replayed: true başlığıyla geri alırsınız.

  • Aynı anahtarı başka bir gövdeyle gönderirseniz 422 idempotency_key_reused gelir.
  • İlk istek hâlâ işleniyorsa 409 idempotency_in_progress gelir; biraz sonra tekrar deneyin. Bizim tarafımızda yarıda kalıp hiç cevap verilmeyen bir isteğin anahtarı 10 dakika sonra yeniden kullanılabilir.
  • Yalnızca başarılı cevaplar saklanır: hata aldıysanız düzeltip aynı anahtarla yeniden gönderebilirsiniz. Anahtarlar işletmeye özeldir.
curl -X POST "https://islemde.app/api/v1/jobs" \
  -H "x-api-key: $ISLEMDE_API_KEY" \
  -H "content-type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "customer": {
    "name": "Emre Kaya",
    "phone": "0544 111 22 33"
  },
  "item": {
    "category": "Telefon",
    "brand": "Samsung",
    "model": "Galaxy S23"
  },
  "problem": "Şarj olmuyor.",
  "priority": "normal"
}'

Hatalar

Hatalar HTTP durum koduyla ve hep aynı biçimde gelir. code değişmez, programınız ona bakabilir; message Türkçe ve okunabilirdir, kullanıcıya ya da kayda yazabilirsiniz.

Cevap
{
  "error": {
    "code": "invalid_api_key",
    "message": "API anahtarı geçersiz, süresi dolmuş ya da iptal edilmiş."
  }
}

Gövdesi hatalı bir istekte issues hangi alanın neden reddedildiğini söyler; path iç içe alanları noktayla ayırır. Tanımadığımız alanlar da reddedilir, böylece yazım hataları sessizce kaybolmaz.

Cevap
{
  "error": {
    "code": "invalid_input",
    "message": "Gönderilen bilgilerde hata var.",
    "issues": [
      {
        "path": "customer.phone",
        "message": "Geçerli bir telefon numarası girin."
      },
      {
        "path": "problem",
        "message": "Sorunu kısaca yazın."
      }
    ]
  }
}
DurumKodAnlamı
400invalid_inputParametre ya da gövde hatalı; issues hangi alanın neden reddedildiğini söyler.
400invalid_jsonGövde geçerli bir JSON değil.
400invalid_idempotency_keyIdempotency-Key biçimi hatalı.
401missing_api_keyAnahtar gönderilmedi.
401invalid_api_keyAnahtar yanlış, süresi dolmuş ya da iptal edilmiş.
403plan_feature_lockedİşletmenin paketinde API yok.
403insufficient_scopeAnahtar yalnızca okuyabilir.
403workspace_restrictedÖdeme alınamadığı için hesap salt okunur; yazma kapalı.
403trial_expiredDeneme süresi bitti; hesap salt okunur, yazma kapalı.
403plan_requiredİşletme için önce bir paket seçilmesi gerekiyor; yazma kapalı.
403trial_limit_reachedDeneme süresindeki iş hakkı doldu; yeni iş açılamaz.
403overage_cap_reachedBu ayki ek kullanım sınırına ulaşıldı; yeni iş açılamaz.
403subscription_canceledAbonelik sona erdi; hesap salt okunur, yazma kapalı.
403forbiddenAnahtarın bu kayda erişimi yok.
404not_foundBöyle bir kayıt yok.
409conflictKayıt az önce değişti ya da istek şu an yerine getirilemiyor; güncel hâli alıp tekrar deneyin.
409phone_in_useTelefon başka bir müşteriye kayıtlı.
409idempotency_in_progressAynı Idempotency-Key ile gönderilen istek hâlâ işleniyor.
409refund_exceeds_paidİade, iş için alınan ödemeden (eksi önceki iadeler) fazla.
413payload_too_largeGövde 64 KB'tan büyük.
422idempotency_key_reusedIdempotency-Key son 24 saatte başka bir gövdeyle kullanıldı.
429rate_limitedDakikalık istek ya da yazma sınırını geçtiniz; Retry-After kadar saniye bekleyin.
500internal_errorBizde bir sorun oldu; kaydı tuttuk.

Sınırlar

Her anahtar dakikada 600 istek yapabilir; bunların en fazla 120 tanesi yazma olabilir. İstek gövdesi en fazla 64 KB. Sınırı aşınca 429 gelir; Retry-After başlığındaki saniye kadar bekleyip devam edin. Değişiklikleri sık sık çekiyorsanız hepsini yeniden okumak yerine changedSince ile yalnızca son kontrolden beri değişenleri isteyin.

OpenAPI

Bütün uçlar ve alanlar OpenAPI 3.1 biçiminde de var. Postman ya da Insomnia'ya içe aktarın, ya da kendi dilinizde istemci üretin. Webhook olaylarının gövdeleri de belgenin webhooks bölümünde.

/api/v1/openapi.json

Bütün işleri tabloya aktarın

Excel ya da Google E-Tablolar için her işi tek bir CSV dosyasına yazın. Kaç sayfa olduğunu düşünmenize gerek yok; yardımcı hepsini sırayla getirir.

  1. state=all ile açık ve kapanmış bütün işleri isteyin.
  2. Her iş için istediğiniz alanları bir satıra yazın.
  3. Dosyayı Excel'de açın; Türkçe karakterler için UTF-8 seçin.
import { writeFile } from "node:fs/promises";
import { all } from "./islemde.js";

const cell = (value) => `"${String(value ?? "").replaceAll('"', '""')}"`;
const rows = [["No", "Müşteri", "Cihaz", "Durum", "Açılış"]];

for await (const job of all("/jobs", { state: "all", limit: 100 })) {
  rows.push([
    job.number,
    job.customer.name,
    [job.item.brand, job.item.model].filter(Boolean).join(" "),
    job.status.label,
    job.createdAt.slice(0, 10),
  ]);
}

await writeFile("isler.csv", rows.map((row) => row.map(cell).join(",")).join("\n"));
isler.csv
No,Müşteri,Cihaz,Durum,Açılış
1057,"Nur Özkan","Apple iPhone 12","Teslime hazır",2026-09-24
1056,"Emre Kaya","Samsung Galaxy S21","Onarımda",2026-09-23

Hazır istemciyi kullanır.

Hazır olan işleri kendi sisteminize bildirin

Kendi SMS sağlayıcınız, CRM'iniz ya da ekip sohbetiniz için: birkaç dakikada bir, son kontrolden beri teslime hazır olan işleri alın.

  1. status=ready ile yalnızca teslime hazır işleri isteyin.
  2. changedSince ile son kontrolden beri durumu değişenleri alın; filtre bizim tarafımızda çalışır.
  3. Kontrol zamanını saklayın ve betiği zamanlayıcıyla (cron) birkaç dakikada bir çalıştırın. İlk çalıştırmada hazır olan bütün işler gelir.
import { readFile, writeFile } from "node:fs/promises";
import { all } from "./islemde.js";

// Kendi SMS, e-posta ya da sohbet gönderiminiz.
const notify = async (text) => console.log(text);

const since = await readFile("son-kontrol.txt", "utf8").catch(() => undefined);
const now = new Date().toISOString();

for await (const job of all("/jobs", { status: "ready", changedSince: since })) {
  await notify(`#${job.number} ${job.customer.name} için hazır: ${job.trackingUrl}`);
}

await writeFile("son-kontrol.txt", now);
Çıktı
#1047 Nur Özkan için hazır: https://islemde.app/t/U7WX42A8

Hazır istemciyi kullanır.

Günün teslimlerini muhasebeye gönderin

Gün sonunda bugün teslim edilen işleri, tutarlarını, alınan ödemeyi ve kalan borcu çıkarın. Hepsi iş listesinde; işleri tek tek açmanız gerekmez.

  1. state=done ve bugünün başlangıcıyla changedSince isteyin; yalnızca bugün kapananlar gelir.
  2. deliveredAt boş olanlar iptal edilmiştir; onları atlayın.
  3. Her işte chargeKurus tutarı, paidKurus alınanı, balanceKurus kalan borcu verir. Tutarlar kuruştur: 350000, ₺3.500,00 demektir.
  4. Teslim edilmiş ama ödenmemiş işlerin tamamı için paymentStatus=owed ile listeleyin.
  5. Müşteri başına toplam için /customers?owing=true isteyin; her müşterinin owedKurus alanı kalan borcudur.
import { all } from "./islemde.js";

const startOfDay = new Date(new Date().setHours(0, 0, 0, 0)).toISOString();
const lira = (kurus) =>
  new Intl.NumberFormat("tr-TR", { style: "currency", currency: "TRY" }).format(kurus / 100);
let paid = 0;
let owed = 0;

for await (const job of all("/jobs", { state: "done", changedSince: startOfDay })) {
  if (!job.deliveredAt) continue; // iptal edilen

  const left = Math.max(0, job.balanceKurus ?? 0); // ücretsizde 0, tutar yoksa null
  paid += job.paidKurus;
  owed += left;
  console.log(job.number, job.customer.name, lira(job.chargeKurus ?? 0), lira(job.paidKurus), lira(left));
}

console.log("Alınan", lira(paid), "· Kalan", lira(owed));
Çıktı
1047 Nur Özkan 3.500,00 TL 3.500,00 TL 0,00 TL
1041 Emre Kaya 1.250,00 TL 500,00 TL 750,00 TL
Alınan 4.000,00 TL · Kalan 750,00 TL

Hazır istemciyi kullanır.

İşleri listele

GET/api/v1/jobs

En yeniden eskiye, sayfa sayfa.

Parametreler

AdAçıklama
statemetinAçık işler, kapananlar ya da hepsi.activedoneall Varsayılan: active.
statusmetinYalnızca bu durumdakiler; durumun anahtarı.
qmetinİş numarası, müşteri adı, telefon ya da cihazda arar.
changedSincemetinYalnızca durumu bu andan sonra değişenler; ISO 8601, örn. 2026-09-26T00:00:00Z. Değişiklikleri düzenli çekmek için.
paymentStatusmetinÖdeme durumuna göre: paid, partial, unpaid, waived, none; balance bakiyesi olanlar, owed teslim edilmiş ama ödenmemiş (veresiye) işler. owed ile state gönderilmezse all sayılır.paidpartialunpaidwaivednonebalanceowed
limitsayıSayfa başına kayıt, 1–100. Varsayılan: 25.
cursormetinÖnceki cevabın nextCursor değeri; ilk sayfada göndermeyin.
İstek
curl "https://islemde.app/api/v1/jobs?status=ready" \
  -H "x-api-key: $ISLEMDE_API_KEY"
Cevap
{
  "data": [
    {
      "number": 1047,
      "trackingCode": "U7WX42A8",
      "trackingUrl": "https://islemde.app/t/U7WX42A8",
      "status": {
        "key": "ready",
        "label": "Teslime hazır",
        "category": "open"
      },
      "item": {
        "category": "Telefon",
        "brand": "Apple",
        "model": "iPhone 12"
      },
      "problem": "Ekran değişimi.",
      "priority": "normal",
      "customer": {
        "name": "Nur Özkan",
        "phone": "+905321234567"
      },
      "assignee": "Burak Demir",
      "estimateKurus": 350000,
      "chargeKurus": 350000,
      "paidKurus": 100000,
      "balanceKurus": 250000,
      "paymentStatus": "partial",
      "dueAt": "2026-09-27T15:00:00.000Z",
      "createdAt": "2026-09-24T08:12:40.000Z",
      "statusChangedAt": "2026-09-25T13:02:11.000Z",
      "deliveredAt": null,
      "cancelledAt": null
    }
  ],
  "nextCursor": "1046"
}

data içindeki her kayıt

AlanAçıklama
numbersayıİş numarası; panelde #1047 olarak görünür.
trackingCodemetinMüşterinin takip kodu (8 karakter).
trackingUrlmetinMüşteriye gönderebileceğiniz takip sayfası. Alan adınız bağlıysa o adreste, değilse islemde.app'te; API'de ve webhook'larda aynıdır.
statusnesneGüncel durum.
status.keymetinDurumun anahtarı: received, ready, delivered…
status.labelmetinPanelde görünen adı.
status.categorymetinDurumun türü.openwaitingdonecancelled
itemnesneCihaz ya da ürün.
item.categorymetin · null olabilirTür, örn. Telefon.
item.brandmetin · null olabilirMarka.
item.modelmetin · null olabilirModel.
problemmetinMüşterinin bildirdiği sorun.
prioritymetinÖncelik.lownormalhighurgent
customernesneMüşteri.
customer.namemetinAd soyad.
customer.phonemetin · null olabilirTelefon, +90 ile.
assigneemetin · null olabilirAtanan kişinin adı.
estimateKurussayı · null olabilirTeslim alırken verilen tahmini tutar, kuruş (185000 = ₺1.850,00).
chargeKurussayı · null olabilirİşin tutarı, kuruş: onaylanan teklifin KDV dahil toplamı, yoksa tahmini tutar. İptal edilen işte null.
paidKurussayıAlınan ödemeler eksi iadeler, kuruş. İptal edilen kayıtlar sayılmaz.
balanceKurussayı · null olabilirKalan borç, kuruş: chargeKurus − paidKurus. Ücretsiz sayılan işte 0, tutar belli değilse null; fazla ödemede eksi olur.
paymentStatusmetinÖdeme durumu: paid ödendi, partial kısmen ödendi, unpaid ödenmedi, waived ücretsiz / garanti kapsamında, none tutar yok. CSV ile aktarılan işler ödeme alınmadıkça none olur.paidpartialunpaidwaivednone
dueAttarih (ISO 8601) · null olabilirSöz verilen teslim tarihi.
createdAttarih (ISO 8601)Teslim alındığı an.
statusChangedAttarih (ISO 8601)Durumun son değiştiği an.
deliveredAttarih (ISO 8601) · null olabilirTeslim edildiği an.
cancelledAttarih (ISO 8601) · null olabilirİptal edildiği an.

Tek iş

GET/api/v1/jobs/{number}

İş ve en yeni geçmiş sayfaları: en fazla 30 olay, 10 teklif ve 10 garanti. Timeline yalnızca müşteriye görünür olayları içerdiğinden boş olabilir. Her liste için pagination içindeki nextCursor veya prevCursor değerini ilgili sorgu parametresine gönderin; null o yönde başka sayfa olmadığını belirtir.

Parametreler

AdAçıklama
numberyol, zorunluİş numarası.
eventsCursormetinpagination.events içindeki nextCursor veya prevCursor; ilk sayfada göndermeyin. En fazla 2048 karakter.
quotesCursormetinpagination.quotes içindeki nextCursor veya prevCursor; ilk sayfada göndermeyin. En fazla 2048 karakter.
warrantiesCursormetinpagination.warranties içindeki nextCursor veya prevCursor; ilk sayfada göndermeyin. En fazla 2048 karakter.
İstek
curl "https://islemde.app/api/v1/jobs/1047" \
  -H "x-api-key: $ISLEMDE_API_KEY"
Cevap
{
  "pagination": {
    "events": {
      "nextCursor": null,
      "prevCursor": null
    },
    "quotes": {
      "nextCursor": null,
      "prevCursor": null
    },
    "warranties": {
      "nextCursor": null,
      "prevCursor": null
    }
  },
  "data": {
    "number": 1047,
    "trackingCode": "U7WX42A8",
    "trackingUrl": "https://islemde.app/t/U7WX42A8",
    "status": {
      "key": "ready",
      "label": "Teslime hazır",
      "category": "open"
    },
    "item": {
      "category": "Telefon",
      "brand": "Apple",
      "model": "iPhone 12"
    },
    "problem": "Ekran değişimi.",
    "priority": "normal",
    "customer": {
      "name": "Nur Özkan",
      "phone": "+905321234567",
      "email": null
    },
    "assignee": "Burak Demir",
    "estimateKurus": 350000,
    "chargeKurus": 350000,
    "paidKurus": 100000,
    "balanceKurus": 250000,
    "paymentStatus": "partial",
    "dueAt": "2026-09-27T15:00:00.000Z",
    "createdAt": "2026-09-24T08:12:40.000Z",
    "statusChangedAt": "2026-09-25T13:02:11.000Z",
    "deliveredAt": null,
    "cancelledAt": null,
    "serial": "356789104455120",
    "accessories": "Kılıf",
    "timeline": [
      {
        "type": "created",
        "at": "2026-09-24T08:12:40.000Z",
        "text": "Cihazınız teslim alındı"
      },
      {
        "type": "status_changed",
        "at": "2026-09-25T13:02:11.000Z",
        "text": "Teslime hazır"
      }
    ],
    "quotes": [
      {
        "number": 212,
        "status": "approved",
        "totalKurus": 350000,
        "validUntil": "2026-10-01T00:00:00.000Z"
      }
    ],
    "warranties": []
  }
}

data

AlanAçıklama
numbersayıİş numarası; panelde #1047 olarak görünür.
trackingCodemetinMüşterinin takip kodu (8 karakter).
trackingUrlmetinMüşteriye gönderebileceğiniz takip sayfası. Alan adınız bağlıysa o adreste, değilse islemde.app'te; API'de ve webhook'larda aynıdır.
statusnesneGüncel durum.
status.keymetinDurumun anahtarı: received, ready, delivered…
status.labelmetinPanelde görünen adı.
status.categorymetinDurumun türü.openwaitingdonecancelled
itemnesneCihaz ya da ürün.
item.categorymetin · null olabilirTür, örn. Telefon.
item.brandmetin · null olabilirMarka.
item.modelmetin · null olabilirModel.
problemmetinMüşterinin bildirdiği sorun.
prioritymetinÖncelik.lownormalhighurgent
customernesneMüşteri.
customer.namemetinAd soyad.
customer.phonemetin · null olabilirTelefon, +90 ile.
customer.emailmetin · null olabilirE-posta.
assigneemetin · null olabilirAtanan kişinin adı.
estimateKurussayı · null olabilirTeslim alırken verilen tahmini tutar, kuruş (185000 = ₺1.850,00).
chargeKurussayı · null olabilirİşin tutarı, kuruş: onaylanan teklifin KDV dahil toplamı, yoksa tahmini tutar. İptal edilen işte null.
paidKurussayıAlınan ödemeler eksi iadeler, kuruş. İptal edilen kayıtlar sayılmaz.
balanceKurussayı · null olabilirKalan borç, kuruş: chargeKurus − paidKurus. Ücretsiz sayılan işte 0, tutar belli değilse null; fazla ödemede eksi olur.
paymentStatusmetinÖdeme durumu: paid ödendi, partial kısmen ödendi, unpaid ödenmedi, waived ücretsiz / garanti kapsamında, none tutar yok. CSV ile aktarılan işler ödeme alınmadıkça none olur.paidpartialunpaidwaivednone
dueAttarih (ISO 8601) · null olabilirSöz verilen teslim tarihi.
createdAttarih (ISO 8601)Teslim alındığı an.
statusChangedAttarih (ISO 8601)Durumun son değiştiği an.
deliveredAttarih (ISO 8601) · null olabilirTeslim edildiği an.
cancelledAttarih (ISO 8601) · null olabilirİptal edildiği an.
serialmetin · null olabilirSeri ya da IMEI numarası.
accessoriesmetin · null olabilirCihazla birlikte bırakılanlar, örn. Kılıf, şarj aleti.
timeline[]listeMüşterinin de gördüğü geçmiş, eskiden yeniye. İç notlar yer almaz.
timeline[].typemetincreated, status_changed, quote_sent…
timeline[].attarih (ISO 8601)Olduğu an.
timeline[].textmetinMüşterinin takip sayfasında gördüğü cümle, örn. Teslime hazır.
quotes[]listeTeklifler.
quotes[].numbersayıTeklif numarası.
quotes[].statusmetinDurumu.draftsentapprovedrejectedexpiredcancelled
quotes[].totalKurussayıKDV dahil toplam, kuruş.
quotes[].validUntiltarih (ISO 8601) · null olabilirSon geçerlilik tarihi.
warranties[]listeGaranti belgeleri.
warranties[].codemetinBelge kodu.
warranties[].statusmetinactive ya da void.
warranties[].monthssayıSüre, ay.
warranties[].endsAttarih (ISO 8601)Bitiş tarihi.

İş aç

POST/api/v1/jobs

Kayıtlı bir müşteriye ya da yeni bir müşteriyle iş açar. Paneldeki gibi işlem hakkından düşer, müşteriye teslim SMS'i gider ve job.created olayı yayılır.

Okuma ve yazma yetkili anahtar gerekir. Idempotency-Key ile güvenle tekrar denenebilir.

Gövde (JSON)

AlanAçıklama
customerIdmetinKayıtlı müşterinin kimliği. Ya customerId ya da customer gönderin.
customernesneYeni müşteri. Aynı telefonla kayıtlı bir müşteri varsa yenisi açılmaz, iş ona bağlanır.
customer.namemetin · zorunluAd soyad ya da firma adı, 2–120 karakter.
customer.phonemetinTelefon; 0532 123 45 67, 5321234567 ya da +905321234567 yazılabilir.
customer.emailmetinE-posta.
customer.kindmetinBireysel ya da kurumsal. Varsayılan: individual.individualcompany
customer.taxIdmetinVergi no (10 hane) ya da T.C. kimlik no (11 hane). Geri okunmaz.
customer.taxOfficemetinVergi dairesi.
customer.citymetinİl, Türkçe yazımıyla: İstanbul, İzmir…
customer.districtmetinİlçe; il ile birlikte gönderin.
customer.addressmetinAçık adres, en fazla 300 karakter.
customer.notesmetinMüşteri hakkında ekibe not. Geri okunmaz.
itemnesneCihaz ya da ürün.
item.categorymetinTür, örn. Telefon.
item.brandmetinMarka.
item.modelmetinModel.
problemmetin · zorunluMüşterinin bildirdiği sorun, 3–2000 karakter.
serialmetinSeri ya da IMEI numarası.
accessoriesmetinCihazla birlikte bırakılanlar.
intakeConditionmetinTeslim alındığındaki durumu: çizik, kırık…
estimateKurussayıTahmini tutar, kuruş (185000 = ₺1.850,00).
prioritymetinÖncelik. Varsayılan: normal.lownormalhighurgent
dueAttarih (ISO 8601)Söz verilen teslim tarihi; ISO 8601.
privateNotemetinEkibe özel not. API ve webhook'lar bunu hiçbir zaman geri göndermez.
İstek
curl -X POST "https://islemde.app/api/v1/jobs" \
  -H "x-api-key: $ISLEMDE_API_KEY" \
  -H "content-type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "customer": {
    "name": "Emre Kaya",
    "phone": "0544 111 22 33"
  },
  "item": {
    "category": "Telefon",
    "brand": "Samsung",
    "model": "Galaxy S23"
  },
  "problem": "Şarj olmuyor.",
  "priority": "normal"
}'
Cevap
{
  "data": {
    "number": 1058,
    "trackingCode": "K3PX9M2D",
    "trackingUrl": "https://islemde.app/t/K3PX9M2D",
    "status": {
      "key": "received",
      "label": "Teslim alındı",
      "category": "open"
    },
    "item": {
      "category": "Telefon",
      "brand": "Samsung",
      "model": "Galaxy S23"
    },
    "problem": "Şarj olmuyor.",
    "priority": "normal",
    "customer": {
      "name": "Emre Kaya",
      "phone": "+905441112233"
    },
    "assignee": null,
    "estimateKurus": null,
    "chargeKurus": null,
    "paidKurus": 0,
    "balanceKurus": null,
    "paymentStatus": "none",
    "dueAt": null,
    "createdAt": "2026-09-27T09:30:00.000Z",
    "statusChangedAt": "2026-09-27T09:30:00.000Z",
    "deliveredAt": null,
    "cancelledAt": null
  }
}

data

AlanAçıklama
numbersayıİş numarası; panelde #1047 olarak görünür.
trackingCodemetinMüşterinin takip kodu (8 karakter).
trackingUrlmetinMüşteriye gönderebileceğiniz takip sayfası. Alan adınız bağlıysa o adreste, değilse islemde.app'te; API'de ve webhook'larda aynıdır.
statusnesneGüncel durum.
status.keymetinDurumun anahtarı: received, ready, delivered…
status.labelmetinPanelde görünen adı.
status.categorymetinDurumun türü.openwaitingdonecancelled
itemnesneCihaz ya da ürün.
item.categorymetin · null olabilirTür, örn. Telefon.
item.brandmetin · null olabilirMarka.
item.modelmetin · null olabilirModel.
problemmetinMüşterinin bildirdiği sorun.
prioritymetinÖncelik.lownormalhighurgent
customernesneMüşteri.
customer.namemetinAd soyad.
customer.phonemetin · null olabilirTelefon, +90 ile.
assigneemetin · null olabilirAtanan kişinin adı.
estimateKurussayı · null olabilirTeslim alırken verilen tahmini tutar, kuruş (185000 = ₺1.850,00).
chargeKurussayı · null olabilirİşin tutarı, kuruş: onaylanan teklifin KDV dahil toplamı, yoksa tahmini tutar. İptal edilen işte null.
paidKurussayıAlınan ödemeler eksi iadeler, kuruş. İptal edilen kayıtlar sayılmaz.
balanceKurussayı · null olabilirKalan borç, kuruş: chargeKurus − paidKurus. Ücretsiz sayılan işte 0, tutar belli değilse null; fazla ödemede eksi olur.
paymentStatusmetinÖdeme durumu: paid ödendi, partial kısmen ödendi, unpaid ödenmedi, waived ücretsiz / garanti kapsamında, none tutar yok. CSV ile aktarılan işler ödeme alınmadıkça none olur.paidpartialunpaidwaivednone
dueAttarih (ISO 8601) · null olabilirSöz verilen teslim tarihi.
createdAttarih (ISO 8601)Teslim alındığı an.
statusChangedAttarih (ISO 8601)Durumun son değiştiği an.
deliveredAttarih (ISO 8601) · null olabilirTeslim edildiği an.
cancelledAttarih (ISO 8601) · null olabilirİptal edildiği an.

İşi düzelt

PATCH/api/v1/jobs/{number}

Yalnızca gönderdiğiniz alanlar değişir; null gönderdiğiniz alan temizlenir. İşin geçmişine ekip için kaydedilir; imzalı teslim fişi olduğu gibi kalır.

Okuma ve yazma yetkili anahtar gerekir.

Parametreler

AdAçıklama
numberyol, zorunluİş numarası.

Gövde (JSON)

AlanAçıklama
itemnesneCihaz ya da ürün.
item.categorymetinTür, örn. Telefon.
item.brandmetinMarka.
item.modelmetinModel.
problemmetinMüşterinin bildirdiği sorun, 3–2000 karakter.
serialmetin · null temizlerSeri ya da IMEI numarası.
accessoriesmetin · null temizlerCihazla birlikte bırakılanlar.
intakeConditionmetin · null temizlerTeslim alındığındaki durumu: çizik, kırık…
estimateKurussayı · null temizlerTahmini tutar, kuruş (185000 = ₺1.850,00).
prioritymetinÖncelik. Varsayılan: normal.lownormalhighurgent
dueAttarih (ISO 8601) · null temizlerSöz verilen teslim tarihi; ISO 8601.
privateNotemetin · null temizlerEkibe özel not. API ve webhook'lar bunu hiçbir zaman geri göndermez.
İstek
curl -X PATCH "https://islemde.app/api/v1/jobs/1047" \
  -H "x-api-key: $ISLEMDE_API_KEY" \
  -H "content-type: application/json" \
  -d '{
  "item": {
    "model": "iPhone 12 Pro"
  },
  "estimateKurus": 420000,
  "dueAt": null
}'
Cevap
{
  "data": {
    "number": 1047,
    "trackingCode": "U7WX42A8",
    "trackingUrl": "https://islemde.app/t/U7WX42A8",
    "status": {
      "key": "ready",
      "label": "Teslime hazır",
      "category": "open"
    },
    "item": {
      "category": "Telefon",
      "brand": "Apple",
      "model": "iPhone 12 Pro"
    },
    "problem": "Ekran değişimi.",
    "priority": "normal",
    "customer": {
      "name": "Nur Özkan",
      "phone": "+905321234567"
    },
    "assignee": "Burak Demir",
    "estimateKurus": 420000,
    "chargeKurus": 350000,
    "paidKurus": 100000,
    "balanceKurus": 250000,
    "paymentStatus": "partial",
    "dueAt": null,
    "createdAt": "2026-09-24T08:12:40.000Z",
    "statusChangedAt": "2026-09-25T13:02:11.000Z",
    "deliveredAt": null,
    "cancelledAt": null
  }
}

data

AlanAçıklama
numbersayıİş numarası; panelde #1047 olarak görünür.
trackingCodemetinMüşterinin takip kodu (8 karakter).
trackingUrlmetinMüşteriye gönderebileceğiniz takip sayfası. Alan adınız bağlıysa o adreste, değilse islemde.app'te; API'de ve webhook'larda aynıdır.
statusnesneGüncel durum.
status.keymetinDurumun anahtarı: received, ready, delivered…
status.labelmetinPanelde görünen adı.
status.categorymetinDurumun türü.openwaitingdonecancelled
itemnesneCihaz ya da ürün.
item.categorymetin · null olabilirTür, örn. Telefon.
item.brandmetin · null olabilirMarka.
item.modelmetin · null olabilirModel.
problemmetinMüşterinin bildirdiği sorun.
prioritymetinÖncelik.lownormalhighurgent
customernesneMüşteri.
customer.namemetinAd soyad.
customer.phonemetin · null olabilirTelefon, +90 ile.
assigneemetin · null olabilirAtanan kişinin adı.
estimateKurussayı · null olabilirTeslim alırken verilen tahmini tutar, kuruş (185000 = ₺1.850,00).
chargeKurussayı · null olabilirİşin tutarı, kuruş: onaylanan teklifin KDV dahil toplamı, yoksa tahmini tutar. İptal edilen işte null.
paidKurussayıAlınan ödemeler eksi iadeler, kuruş. İptal edilen kayıtlar sayılmaz.
balanceKurussayı · null olabilirKalan borç, kuruş: chargeKurus − paidKurus. Ücretsiz sayılan işte 0, tutar belli değilse null; fazla ödemede eksi olur.
paymentStatusmetinÖdeme durumu: paid ödendi, partial kısmen ödendi, unpaid ödenmedi, waived ücretsiz / garanti kapsamında, none tutar yok. CSV ile aktarılan işler ödeme alınmadıkça none olur.paidpartialunpaidwaivednone
dueAttarih (ISO 8601) · null olabilirSöz verilen teslim tarihi.
createdAttarih (ISO 8601)Teslim alındığı an.
statusChangedAttarih (ISO 8601)Durumun son değiştiği an.
deliveredAttarih (ISO 8601) · null olabilirTeslim edildiği an.
cancelledAttarih (ISO 8601) · null olabilirİptal edildiği an.

Durumu değiştir

POST/api/v1/jobs/{number}/status

İşi başka bir adıma taşır. Müşterinin SMS ve e-postası panelden değiştirilmiş gibi gider; delivered teslim eder. Durum anahtarlarını Durumlar ucundan alın.

Okuma ve yazma yetkili anahtar gerekir. Idempotency-Key ile güvenle tekrar denenebilir.

Parametreler

AdAçıklama
numberyol, zorunluİş numarası.

Gövde (JSON)

AlanAçıklama
statusmetinDurumun anahtarı, örn. ready. Ya status ya da statusId gönderin.
statusIdmetinDurumun kimliği.
İstek
curl -X POST "https://islemde.app/api/v1/jobs/1047/status" \
  -H "x-api-key: $ISLEMDE_API_KEY" \
  -H "content-type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "status": "ready"
}'
Cevap
{
  "data": {
    "number": 1047,
    "trackingCode": "U7WX42A8",
    "trackingUrl": "https://islemde.app/t/U7WX42A8",
    "status": {
      "key": "ready",
      "label": "Teslime hazır",
      "category": "open"
    },
    "item": {
      "category": "Telefon",
      "brand": "Apple",
      "model": "iPhone 12"
    },
    "problem": "Ekran değişimi.",
    "priority": "normal",
    "customer": {
      "name": "Nur Özkan",
      "phone": "+905321234567"
    },
    "assignee": "Burak Demir",
    "estimateKurus": 350000,
    "chargeKurus": 350000,
    "paidKurus": 100000,
    "balanceKurus": 250000,
    "paymentStatus": "partial",
    "dueAt": "2026-09-27T15:00:00.000Z",
    "createdAt": "2026-09-24T08:12:40.000Z",
    "statusChangedAt": "2026-09-25T13:02:11.000Z",
    "deliveredAt": null,
    "cancelledAt": null
  }
}

data

AlanAçıklama
numbersayıİş numarası; panelde #1047 olarak görünür.
trackingCodemetinMüşterinin takip kodu (8 karakter).
trackingUrlmetinMüşteriye gönderebileceğiniz takip sayfası. Alan adınız bağlıysa o adreste, değilse islemde.app'te; API'de ve webhook'larda aynıdır.
statusnesneGüncel durum.
status.keymetinDurumun anahtarı: received, ready, delivered…
status.labelmetinPanelde görünen adı.
status.categorymetinDurumun türü.openwaitingdonecancelled
itemnesneCihaz ya da ürün.
item.categorymetin · null olabilirTür, örn. Telefon.
item.brandmetin · null olabilirMarka.
item.modelmetin · null olabilirModel.
problemmetinMüşterinin bildirdiği sorun.
prioritymetinÖncelik.lownormalhighurgent
customernesneMüşteri.
customer.namemetinAd soyad.
customer.phonemetin · null olabilirTelefon, +90 ile.
assigneemetin · null olabilirAtanan kişinin adı.
estimateKurussayı · null olabilirTeslim alırken verilen tahmini tutar, kuruş (185000 = ₺1.850,00).
chargeKurussayı · null olabilirİşin tutarı, kuruş: onaylanan teklifin KDV dahil toplamı, yoksa tahmini tutar. İptal edilen işte null.
paidKurussayıAlınan ödemeler eksi iadeler, kuruş. İptal edilen kayıtlar sayılmaz.
balanceKurussayı · null olabilirKalan borç, kuruş: chargeKurus − paidKurus. Ücretsiz sayılan işte 0, tutar belli değilse null; fazla ödemede eksi olur.
paymentStatusmetinÖdeme durumu: paid ödendi, partial kısmen ödendi, unpaid ödenmedi, waived ücretsiz / garanti kapsamında, none tutar yok. CSV ile aktarılan işler ödeme alınmadıkça none olur.paidpartialunpaidwaivednone
dueAttarih (ISO 8601) · null olabilirSöz verilen teslim tarihi.
createdAttarih (ISO 8601)Teslim alındığı an.
statusChangedAttarih (ISO 8601)Durumun son değiştiği an.
deliveredAttarih (ISO 8601) · null olabilirTeslim edildiği an.
cancelledAttarih (ISO 8601) · null olabilirİptal edildiği an.

Not ekle

POST/api/v1/jobs/{number}/notes

İşe not ekler. Varsayılan olarak yalnızca ekip görür; customerVisible ile müşterinin takip sayfasında da görünür.

Okuma ve yazma yetkili anahtar gerekir. Idempotency-Key ile güvenle tekrar denenebilir.

Parametreler

AdAçıklama
numberyol, zorunluİş numarası.

Gövde (JSON)

AlanAçıklama
bodymetin · zorunluNot, 1–4000 karakter.
customerVisibleevet/hayırMüşteri de görsün. Varsayılan: false.
İstek
curl -X POST "https://islemde.app/api/v1/jobs/1047/notes" \
  -H "x-api-key: $ISLEMDE_API_KEY" \
  -H "content-type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "body": "Parça siparişi verildi, perşembe gelecek.",
  "customerVisible": true
}'
Cevap
{
  "data": {
    "id": "0f9c2a64-7d0e-4b8f-a0f1-65e0b5d2c7a3",
    "body": "Parça siparişi verildi, perşembe gelecek.",
    "customerVisible": true,
    "author": "API · Muhasebe",
    "createdAt": "2026-09-27T10:05:00.000Z"
  }
}

data

AlanAçıklama
idmetinNotun kimliği.
bodymetinNot.
customerVisibleevet/hayırMüşterinin takip sayfasında da görünür.
authormetinYazan; API'den gelenlerde anahtarın adı.
createdAttarih (ISO 8601)Eklendiği an.

İşin ödemeleri

GET/api/v1/jobs/{number}/payments

İşe kaydedilen ödemeler ve iadeler, yeniden eskiye; iptal edilenler voidedAt ile birlikte. Kalan borç işin balanceKurus alanında.

Parametreler

AdAçıklama
numberyol, zorunluİş numarası.
İstek
curl "https://islemde.app/api/v1/jobs/1047/payments" \
  -H "x-api-key: $ISLEMDE_API_KEY"
Cevap
{
  "data": [
    {
      "id": "8d3f0c1e-54a2-4a71-9b7e-2f6a1c0d9e44",
      "kind": "payment",
      "amountKurus": 100000,
      "method": "cash",
      "note": "Kapora",
      "receivedAt": "2026-09-24T08:14:02.000Z",
      "receivedBy": "Selin Aydın",
      "atHandover": false,
      "voidedAt": null,
      "voidReason": null
    }
  ]
}

data içindeki her kayıt

AlanAçıklama
idmetinKaydın kimliği.
kindmetinpayment alınan ödeme, refund müşteriye yapılan iade.paymentrefund
amountKurussayıTutar, kuruş; her zaman artı.
methodmetincash nakit, card kart (işletmenin kendi POS'u), transfer havale / EFT, other diğer.cashcardtransferother
notemetin · null olabilirNot.
receivedAttarih (ISO 8601)Ödemenin alındığı an.
receivedBymetin · null olabilirKaydı giren; API'den gelenlerde anahtarın adı.
atHandoverevet/hayırTeslim sırasında alındı.
voidedAttarih (ISO 8601) · null olabilirİptal edildiyse o an; iptal edilen kayıt hesaba katılmaz.
voidReasonmetin · null olabilirİptal nedeni.

Ödeme kaydet

POST/api/v1/jobs/{number}/payments

Ödeme ya da iade kaydeder; panelden alınmış gibi işin bakiyesi, kasa ve raporlar güncellenir, payment.recorded olayı yayılır. İşlemde para çekmez, yalnızca alınan ödemeyi kaydeder. Tekrar denerken aynı Idempotency-Key'i gönderin; 24 saat içinde ödeme iki kez yazılmaz.

Okuma ve yazma yetkili anahtar gerekir. Idempotency-Key ile güvenle tekrar denenebilir.

Parametreler

AdAçıklama
numberyol, zorunluİş numarası.

Gövde (JSON)

AlanAçıklama
kindmetinpayment ya da refund. Varsayılan: payment.paymentrefund
amountKurussayı · zorunluTutar, kuruş; 1 ile 100000000 (₺1.000.000) arası.
methodmetin · zorunluÖdeme şekli.cashcardtransferother
notemetinNot, en fazla 300 karakter.
İstek
curl -X POST "https://islemde.app/api/v1/jobs/1047/payments" \
  -H "x-api-key: $ISLEMDE_API_KEY" \
  -H "content-type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "amountKurus": 250000,
  "method": "card",
  "note": "Kalan ödeme"
}'
Cevap
{
  "data": {
    "payment": {
      "id": "c41b7a2e-0f3d-4e8a-9a55-7d21e6b0f913",
      "kind": "payment",
      "amountKurus": 250000,
      "method": "card",
      "note": "Kalan ödeme",
      "receivedAt": "2026-09-27T16:40:12.000Z",
      "receivedBy": "API · Muhasebe",
      "atHandover": false,
      "voidedAt": null,
      "voidReason": null
    },
    "job": {
      "number": 1047,
      "trackingCode": "U7WX42A8",
      "trackingUrl": "https://islemde.app/t/U7WX42A8",
      "status": {
        "key": "ready",
        "label": "Teslime hazır",
        "category": "open"
      },
      "item": {
        "category": "Telefon",
        "brand": "Apple",
        "model": "iPhone 12"
      },
      "problem": "Ekran değişimi.",
      "priority": "normal",
      "customer": {
        "name": "Nur Özkan",
        "phone": "+905321234567"
      },
      "assignee": "Burak Demir",
      "estimateKurus": 350000,
      "chargeKurus": 350000,
      "paidKurus": 350000,
      "balanceKurus": 0,
      "paymentStatus": "paid",
      "dueAt": "2026-09-27T15:00:00.000Z",
      "createdAt": "2026-09-24T08:12:40.000Z",
      "statusChangedAt": "2026-09-25T13:02:11.000Z",
      "deliveredAt": null,
      "cancelledAt": null
    }
  }
}

data

AlanAçıklama
paymentnesneKayıt.
payment.idmetinKaydın kimliği.
payment.kindmetinpayment alınan ödeme, refund müşteriye yapılan iade.paymentrefund
payment.amountKurussayıTutar, kuruş; her zaman artı.
payment.methodmetincash nakit, card kart (işletmenin kendi POS'u), transfer havale / EFT, other diğer.cashcardtransferother
payment.notemetin · null olabilirNot.
payment.receivedAttarih (ISO 8601)Ödemenin alındığı an.
payment.receivedBymetin · null olabilirKaydı giren; API'den gelenlerde anahtarın adı.
payment.atHandoverevet/hayırTeslim sırasında alındı.
payment.voidedAttarih (ISO 8601) · null olabilirİptal edildiyse o an; iptal edilen kayıt hesaba katılmaz.
payment.voidReasonmetin · null olabilirİptal nedeni.
jobnesneİşin kayıttan sonraki hâli; balanceKurus kalan borcu söyler.
job.numbersayıİş numarası; panelde #1047 olarak görünür.
job.trackingCodemetinMüşterinin takip kodu (8 karakter).
job.trackingUrlmetinMüşteriye gönderebileceğiniz takip sayfası. Alan adınız bağlıysa o adreste, değilse islemde.app'te; API'de ve webhook'larda aynıdır.
job.statusnesneGüncel durum.
job.status.keymetinDurumun anahtarı: received, ready, delivered…
job.status.labelmetinPanelde görünen adı.
job.status.categorymetinDurumun türü.openwaitingdonecancelled
job.itemnesneCihaz ya da ürün.
job.item.categorymetin · null olabilirTür, örn. Telefon.
job.item.brandmetin · null olabilirMarka.
job.item.modelmetin · null olabilirModel.
job.problemmetinMüşterinin bildirdiği sorun.
job.prioritymetinÖncelik.lownormalhighurgent
job.customernesneMüşteri.
job.customer.namemetinAd soyad.
job.customer.phonemetin · null olabilirTelefon, +90 ile.
job.assigneemetin · null olabilirAtanan kişinin adı.
job.estimateKurussayı · null olabilirTeslim alırken verilen tahmini tutar, kuruş (185000 = ₺1.850,00).
job.chargeKurussayı · null olabilirİşin tutarı, kuruş: onaylanan teklifin KDV dahil toplamı, yoksa tahmini tutar. İptal edilen işte null.
job.paidKurussayıAlınan ödemeler eksi iadeler, kuruş. İptal edilen kayıtlar sayılmaz.
job.balanceKurussayı · null olabilirKalan borç, kuruş: chargeKurus − paidKurus. Ücretsiz sayılan işte 0, tutar belli değilse null; fazla ödemede eksi olur.
job.paymentStatusmetinÖdeme durumu: paid ödendi, partial kısmen ödendi, unpaid ödenmedi, waived ücretsiz / garanti kapsamında, none tutar yok. CSV ile aktarılan işler ödeme alınmadıkça none olur.paidpartialunpaidwaivednone
job.dueAttarih (ISO 8601) · null olabilirSöz verilen teslim tarihi.
job.createdAttarih (ISO 8601)Teslim alındığı an.
job.statusChangedAttarih (ISO 8601)Durumun son değiştiği an.
job.deliveredAttarih (ISO 8601) · null olabilirTeslim edildiği an.
job.cancelledAttarih (ISO 8601) · null olabilirİptal edildiği an.

Müşterileri listele

GET/api/v1/customers

En son iş getirenden başlayarak, sayfa sayfa.

Parametreler

AdAçıklama
qmetinAd, telefon ya da e-postada arar.
owingmetintrue ile yalnızca teslim edilmiş işlerden borcu kalan müşteriler.truefalse Varsayılan: false.
limitsayıSayfa başına kayıt, 1–100. Varsayılan: 25.
cursormetinÖnceki cevabın nextCursor değeri; ilk sayfada göndermeyin.
İstek
curl "https://islemde.app/api/v1/customers" \
  -H "x-api-key: $ISLEMDE_API_KEY"
Cevap
{
  "data": [
    {
      "id": "c30f5268-a5a7-4269-a9c0-bc135f6a90ae",
      "name": "Nur Özkan",
      "phone": "+905321234567",
      "email": null,
      "jobCount": 3,
      "lastJobAt": "2026-09-24T08:12:40.000Z",
      "owedKurus": 250000,
      "createdAt": "2026-06-02T10:40:00.000Z"
    }
  ],
  "nextCursor": null
}

data içindeki her kayıt

AlanAçıklama
idmetinMüşterinin kimliği.
namemetinAd soyad.
phonemetin · null olabilirTelefon, +90 ile.
emailmetin · null olabilirE-posta.
jobCountsayıToplam iş sayısı.
lastJobAttarih (ISO 8601) · null olabilirSon işin açıldığı an.
owedKurussayıTeslim edilmiş ama ödenmemiş işlerden kalan borç (veresiye), kuruş. Ücretsiz sayılan ve CSV ile aktarılan işler sayılmaz; borç yoksa 0.
createdAttarih (ISO 8601)Kaydın açıldığı an.

Tek müşteri

GET/api/v1/customers/{id}

Müşterinin kaydı, iş sayısı ve teslim edilmiş işlerden kalan borcu.

Parametreler

AdAçıklama
idyol, zorunluMüşterinin kimliği.
İstek
curl "https://islemde.app/api/v1/customers/5b1e7f7a-0c1d-4a55-9d51-2f0c8f3b8a10" \
  -H "x-api-key: $ISLEMDE_API_KEY"
Cevap
{
  "data": {
    "id": "5b1e7f7a-0c1d-4a55-9d51-2f0c8f3b8a10",
    "kind": "individual",
    "name": "Emre Kaya",
    "phone": "+905441112233",
    "email": "emre@example.com",
    "city": "İzmir",
    "district": "Karşıyaka",
    "address": null,
    "smsOptOut": false,
    "createdAt": "2026-09-27T09:30:00.000Z",
    "jobCount": 2,
    "owedKurus": 0
  }
}

data

AlanAçıklama
idmetinMüşterinin kimliği.
kindmetinBireysel ya da kurumsal.individualcompany
namemetinAd soyad ya da firma adı.
phonemetin · null olabilirTelefon, +90 ile.
emailmetin · null olabilirE-posta.
citymetin · null olabilirİl.
districtmetin · null olabilirİlçe.
addressmetin · null olabilirAçık adres.
smsOptOutevet/hayırMüşteri SMS almak istemiyor.
createdAttarih (ISO 8601)Kaydın açıldığı an.
jobCountsayıToplam iş sayısı.
owedKurussayıTeslim edilmiş ama ödenmemiş işlerden kalan borç (veresiye), kuruş. Ücretsiz sayılan ve CSV ile aktarılan işler sayılmaz; borç yoksa 0.

Müşteri ekle

POST/api/v1/customers

Yeni müşteri açar ve customer.created olayını yayar. Aynı telefonla kayıtlı bir müşteri varsa 409 döner; o müşteriyi Müşterileri listele ucunda telefonla arayın.

Okuma ve yazma yetkili anahtar gerekir. Idempotency-Key ile güvenle tekrar denenebilir.

Gövde (JSON)

AlanAçıklama
namemetin · zorunluAd soyad ya da firma adı, 2–120 karakter.
phonemetinTelefon; 0532 123 45 67, 5321234567 ya da +905321234567 yazılabilir.
emailmetinE-posta.
kindmetinBireysel ya da kurumsal. Varsayılan: individual.individualcompany
taxIdmetinVergi no (10 hane) ya da T.C. kimlik no (11 hane). Geri okunmaz.
taxOfficemetinVergi dairesi.
citymetinİl, Türkçe yazımıyla: İstanbul, İzmir…
districtmetinİlçe; il ile birlikte gönderin.
addressmetinAçık adres, en fazla 300 karakter.
notesmetinMüşteri hakkında ekibe not. Geri okunmaz.
İstek
curl -X POST "https://islemde.app/api/v1/customers" \
  -H "x-api-key: $ISLEMDE_API_KEY" \
  -H "content-type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "name": "Emre Kaya",
  "phone": "0544 111 22 33",
  "email": "emre@example.com",
  "city": "İzmir",
  "district": "Karşıyaka"
}'
Cevap
{
  "data": {
    "id": "5b1e7f7a-0c1d-4a55-9d51-2f0c8f3b8a10",
    "kind": "individual",
    "name": "Emre Kaya",
    "phone": "+905441112233",
    "email": "emre@example.com",
    "city": "İzmir",
    "district": "Karşıyaka",
    "address": null,
    "smsOptOut": false,
    "createdAt": "2026-09-27T09:30:00.000Z"
  }
}

data

AlanAçıklama
idmetinMüşterinin kimliği.
kindmetinBireysel ya da kurumsal.individualcompany
namemetinAd soyad ya da firma adı.
phonemetin · null olabilirTelefon, +90 ile.
emailmetin · null olabilirE-posta.
citymetin · null olabilirİl.
districtmetin · null olabilirİlçe.
addressmetin · null olabilirAçık adres.
smsOptOutevet/hayırMüşteri SMS almak istemiyor.
createdAttarih (ISO 8601)Kaydın açıldığı an.

Müşteriyi düzelt

PATCH/api/v1/customers/{id}

Yalnızca gönderdiğiniz alanlar değişir; null gönderdiğiniz alan temizlenir. Kişisel verileri silinmiş müşteri değiştirilemez.

Okuma ve yazma yetkili anahtar gerekir.

Parametreler

AdAçıklama
idyol, zorunluMüşterinin kimliği.

Gövde (JSON)

AlanAçıklama
namemetinAd soyad ya da firma adı, 2–120 karakter.
phonemetin · null temizlerTelefon; 0532 123 45 67, 5321234567 ya da +905321234567 yazılabilir.
emailmetin · null temizlerE-posta.
kindmetinBireysel ya da kurumsal.individualcompany
taxIdmetin · null temizlerVergi no (10 hane) ya da T.C. kimlik no (11 hane). Geri okunmaz.
taxOfficemetin · null temizlerVergi dairesi.
citymetin · null temizlerİl, Türkçe yazımıyla: İstanbul, İzmir…
districtmetin · null temizlerİlçe; il ile birlikte gönderin.
addressmetin · null temizlerAçık adres, en fazla 300 karakter.
notesmetin · null temizlerMüşteri hakkında ekibe not. Geri okunmaz.
smsOptOutevet/hayırMüşteri SMS almak istemiyor.
İstek
curl -X PATCH "https://islemde.app/api/v1/customers/5b1e7f7a-0c1d-4a55-9d51-2f0c8f3b8a10" \
  -H "x-api-key: $ISLEMDE_API_KEY" \
  -H "content-type: application/json" \
  -d '{
  "email": "emre.kaya@example.com",
  "smsOptOut": true
}'
Cevap
{
  "data": {
    "id": "5b1e7f7a-0c1d-4a55-9d51-2f0c8f3b8a10",
    "kind": "individual",
    "name": "Emre Kaya",
    "phone": "+905441112233",
    "email": "emre.kaya@example.com",
    "city": "İzmir",
    "district": "Karşıyaka",
    "address": null,
    "smsOptOut": true,
    "createdAt": "2026-09-27T09:30:00.000Z"
  }
}

data

AlanAçıklama
idmetinMüşterinin kimliği.
kindmetinBireysel ya da kurumsal.individualcompany
namemetinAd soyad ya da firma adı.
phonemetin · null olabilirTelefon, +90 ile.
emailmetin · null olabilirE-posta.
citymetin · null olabilirİl.
districtmetin · null olabilirİlçe.
addressmetin · null olabilirAçık adres.
smsOptOutevet/hayırMüşteri SMS almak istemiyor.
createdAttarih (ISO 8601)Kaydın açıldığı an.

Durumlar

GET/api/v1/statuses

İşletmenin iş akışındaki adımlar, sırasıyla. Durum değiştirirken ve işleri süzerken bu anahtarları kullanın; işletme adımları yeniden adlandırsa da anahtar değişmez.

İstek
curl "https://islemde.app/api/v1/statuses" \
  -H "x-api-key: $ISLEMDE_API_KEY"
Cevap
{
  "data": [
    {
      "id": "d2b8c1e0-2f4a-4c1b-9a77-1f5e3c9b0a11",
      "key": "received",
      "label": "Teslim alındı",
      "customerLabel": "Cihazınız teslim alındı",
      "category": "open",
      "isInitial": true
    },
    {
      "id": "8a3f6d52-6b1e-4f0d-8c3e-7e2a9b4c5d22",
      "key": "ready",
      "label": "Teslime hazır",
      "customerLabel": "Teslime hazır",
      "category": "open",
      "isInitial": false
    },
    {
      "id": "4c7e9a13-0d2b-4e6f-b1a8-3f5c7d9e1b33",
      "key": "delivered",
      "label": "Teslim edildi",
      "customerLabel": "Teslim edildi",
      "category": "done",
      "isInitial": false
    }
  ]
}

data içindeki her kayıt

AlanAçıklama
idmetinDurumun kimliği.
keymetinDeğişmeyen anahtar: received, repairing, ready, delivered, cancelled…
labelmetinPanelde görünen adı.
customerLabelmetinMüşterinin takip sayfasında gördüğü adı.
categorymetinDurumun türü.openwaitingdonecancelled
isInitialevet/hayırYeni işler bu durumla açılır.

Webhook'lar nasıl çalışır

Durum sorup durmak yerine olup biteni anında alın: bir iş açıldığında, durumu değiştiğinde ya da müşteri teklifi onayladığında İşlemde sizin adresinize bir POST isteği gönderir. Adresi Ayarlar → API → Webhook adresleri bölümünden ekleyin, hangi olayları istediğinizi seçin. İmza anahtarı (whsec_…) yalnızca bir kez gösterilir.

  • Adres https:// ile başlamalı; port 443 ya da 1024 ve üstü olmalı (örneğin 8443). Kullanıcı adı ve şifre içeremez; iç ağa, yerel ağa ya da ayrılmış IP adreslerine çıkan adresler kabul edilmez ve her gönderimde yeniden denetlenir.
  • Gövde, olayın türü ve REST API'deki kayıtların aynısıdır. Ekibe özel notlar, vergi numaraları ve onay bağlantıları hiçbir zaman gönderilmez.
  • Her gövdede apiVersion (şu an 2026-10-01) gelir. Alan eklemek sürümü değiştirmez; bir alan kalkar ya da anlamı değişirse yeni bir tarih alır.
  • Test gönder düğmesi adresinize bir ping olayı yollar; son gönderimleri, cevap kodlarını ve hataları aynı sayfada görürsünüz.
Örnek
{
  "id": "evt_3f9a1c2b7d8e4f60a1b2c3d4e5f60718",
  "type": "job.status_changed",
  "apiVersion": "2026-10-01",
  "createdAt": "2026-09-25T13:02:11.482Z",
  "data": {
    "job": {
      "number": 1047,
      "trackingCode": "U7WX42A8",
      "trackingUrl": "https://islemde.app/t/U7WX42A8",
      "status": {
        "key": "ready",
        "label": "Teslime hazır",
        "category": "open"
      },
      "item": {
        "category": "Telefon",
        "brand": "Apple",
        "model": "iPhone 12"
      },
      "problem": "Ekran değişimi.",
      "priority": "normal",
      "customer": {
        "name": "Nur Özkan",
        "phone": "+905321234567"
      },
      "assignee": "Burak Demir",
      "estimateKurus": 350000,
      "chargeKurus": 350000,
      "paidKurus": 100000,
      "balanceKurus": 250000,
      "paymentStatus": "partial",
      "dueAt": "2026-09-27T15:00:00.000Z",
      "createdAt": "2026-09-24T08:12:40.000Z",
      "statusChangedAt": "2026-09-25T13:02:11.000Z",
      "deliveredAt": null,
      "cancelledAt": null
    },
    "previousStatus": {
      "key": "repairing",
      "label": "Onarımda",
      "category": "open"
    }
  }
}
BaşlıkAnlamı
islemde-eventOlayın türü, örn. job.status_changed. Test gönderiminde ping.
islemde-deliveryBu gönderimin kimliği; tekrar denemelerde aynı kalır.
islemde-signaturet=<unix saniye>,v1=<imza>; anahtar yenilendikten sonraki 24 saatte iki v1 gelir. Doğrulama aşağıda.
content-typeapplication/json
user-agentIslemde-Webhooks/1.0

Olaylar

data içindeki job, İşleri listele ucundaki iş kaydıyla aynıdır; customer, Müşteri ekle ucunun cevabıyla.

OlayNe zamandata
job.createdPanelde, API'den ya da teslim fişiyle iş açıldığında.job
job.updatedİşin bilgileri düzeltildiğinde. Yalnızca ekibe özel not değiştiyse gelmez.job, changes (değişen alanlar)
job.status_changedİş başka bir duruma geçtiğinde; teklif onayıyla kendiliğinden geçişler dahil.job, previousStatus
job.deliveredCihaz teslim edildiğinde. Teslim yeniden yapılırsa bir kez daha gelir.job, handover (teslim alan, ödeme, ücretsiz mi, imza; durum değiştirerek teslimde null)
job.note_addedMüşteriye açık bir not eklendiğinde. Ekip içi notlar gönderilmez.job, note
quote.sentTeklif müşteriye gönderildiğinde.job, quote
quote.approvedMüşteri teklifi imzalayıp onayladığında.job, quote
quote.rejectedMüşteri teklifi reddettiğinde.job, quote
warranty.issuedGaranti belgesi verildiğinde.job, warranty
payment.recordedÖdeme ya da iade kaydedildiğinde: kapora, teslimde ya da sonradan alınan, API'den gelen.job (balanceKurus: kayıttan sonra kalan borç), payment
payment.voidedYanlış girilen bir ödeme ya da iade kaydı iptal edildiğinde.job, payment (voidedAt ve voidReason dolu)
customer.createdPanelde, iş kabulünde ya da API'den yeni müşteri açıldığında. CSV ile içe aktarılanlar için gelmez.customer

İmzayı doğrulama

Her isteğin islemde-signature başlığı t=1790000000,v1=5f2b… biçimindedir. v1, imza anahtarınızla t + "." + gövde metninin HMAC-SHA256 özetidir (küçük harf onaltılık). Kendi hesapladığınızla sabit sürede karşılaştırın ve 5 dakikadan eski t değerlerini reddedin. Gövdeyi ayrıştırmadan, geldiği gibi kullanın: tek bir boşluk bile imzayı bozar.

// Node 18+ ve Express: npm install express
import crypto from "node:crypto";
import express from "express";

const app = express();
const secret = process.env.ISLEMDE_WEBHOOK_SECRET; // whsec_ ile başlar

// İmza ham gövde üzerinden hesaplanır: JSON'u ayrıştırmadan önce doğrulayın.
app.post("/islemde-webhook", express.raw({ type: "application/json" }), (req, res) => {
  const parts = (req.get("islemde-signature") ?? "").split(",").map((part) => part.split("="));
  const t = parts.find(([key]) => key === "t")?.[1];
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${t}.${req.body}`)
    .digest("hex");
  // Anahtar yenilendikten sonraki 24 saatte iki v1 gelir: biri tutması yeter.
  const valid = parts.some(
    ([key, value]) =>
      key === "v1" &&
      value.length === expected.length &&
      crypto.timingSafeEqual(Buffer.from(value), Buffer.from(expected)),
  );
  // 5 dakikadan eski imzaları reddedin: yakalanıp yeniden gönderilen istekler geçmez.
  const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300;
  if (!valid || !fresh) return res.sendStatus(400);

  const event = JSON.parse(req.body);
  // Aynı olay birden fazla gelebilir: event.id'yi saklayıp tekrarları atlayın.
  res.sendStatus(200); // Önce cevap verin; uzun işleri sonra yapın.
  console.log(event.type, event.data.job?.number);
});

app.listen(3000);

Anahtarı yenilediğinizde olaylar 24 saat boyunca iki imzayla gelir: t=…,v1=<yeni>,v1=<eski>. Her v1 değerini deneyin, biri tutuyorsa istek geçerlidir; böylece sunucunuzu bu süre içinde kesintisiz güncelleyebilirsiniz.

Tekrar denemeler

2xx dışındaki her cevap, 5 saniyeyi aşan bekleme, bağlantı hatası ve yönlendirme (3xx) başarısız sayılır; yönlendirmeler izlenmez. Başarısız bir gönderim şu aralıklarla yeniden denenir: 1 dakika, 5 dakika, 30 dakika, 2 saat, 6 saat, 24 saat. Yedinci denemeden sonra vazgeçilir; Ayarlar → API'deki listeden elle yeniden gönderebilirsiniz.

Bir adrese yapılan gönderimler (tekrar denemeler dahil) art arda 20 kez başarısız olur ve 24 saattir hiçbir gönderim ulaşmamışsa adres kapatılır, işletme sahibine bildirim gider. Kısa kesintiler adresi kapatmaz. Adresi düzeltip aynı yerden yeniden açabilirsiniz; kapalıyken oluşan olaylar gönderilmez.

İyi uygulamalar

  • Önce imzayı doğrulayın, sonra hemen 200 dönün; uzun işleri kendi kuyruğunuzda yapın. 5 saniyeyi aşan cevaplar tekrar denenir.
  • Aynı olay birden fazla gelebilir. Olayın id değerini saklayın ve daha önce işlediklerinizi atlayın.
  • Olayların sırası garanti değildir. Güncel hâl için statusChangedAt alanına bakın ya da işi GET /api/v1/jobs/{number} ile yeniden okuyun.
  • Adresiniz uzun süre kapalı kaldıysa aradaki değişiklikleri changedSince ile toplayın.
  • İmza anahtarını da API anahtarı gibi saklayın; sızdığını düşünürseniz yenileyin.

Başka bir uca ihtiyacınız mı var? Panelde Destek bölümünden ya da destek@islemde.app adresinden yazın. Değişiklikler Yenilikler sayfasında duyurulur.