מדריך אינטגרציה לשותפי TEKUNA / DILS
English summary: Hebrew quickstart for the official
@tekuna/sdk-nodeSDK. Install, provision a partner API key, mint your first DILS on Chain 2027, and call every module method. Scroll down for code samples.
@tekuna/sdk-node היא ספריית ה-Node.js הרשמית לאינטגרציה עם תשתית הסליקה הריבונית של TEKUNA / DILS.
עם ה-SDK תוכל:
הכלל הבסיסי: 1 DILS = 1 ש"ח = 100 אגורות. כל הסכומים ב-SDK מועברים באגורות (שלמים) כדי למנוע בעיות עיגול.
fetch).sk_test_dils_… לסנדבוקס או sk_live_dils_… לפרודקשן).https://api.dils.co.il.npm install @tekuna/sdk-node
מפתח השותף נוצר באמצעות בקשת POST ל-/api/sdk/provision עם פרטי KYB:
curl -X POST https://api.dils.co.il/api/sdk/provision \
-H 'Content-Type: application/json' \
-d '{
"kyb": {
"legalEntityId": "514123456",
"name": "חברת הדגמה בע\"מ",
"email": "ceo@demo.co.il",
"address": "רוטשילד 1, תל אביב"
},
"tier": "starter",
"chain": "testnet"
}'
תשובה לדוגמה:
{
"apiKey": "sk_test_dils_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"clubId": "uuid-…",
"customerCardId": "uuid-…",
"walletAddress": "0xabc…",
"chain": "testnet",
"tier": "starter",
"modules": ["clubs", "payments"]
}
⚠️ שמור את ה-apiKey בצורה מאובטחת (Secret Manager / Vault).
המערכת שומרת רק את ה-hash שלו; אין דרך לשחזר אותו.
import { Tekuna } from '@tekuna/sdk-node';
const tekuna = new Tekuna({
apiKey: process.env.TEKUNA_API_KEY!,
});
const tx = await tekuna.dils.mint({ amount_agorot: 10000 });
// ^^^^^^^^^^^^^^^^^^^^^^
// 100 ש"ח (10,000 אגורות)
console.log('Tx hash:', tx.tx_hash);
console.log('Chain:', tx.chain_id); // 2026 לסנדבוקס, 2027 לפרודקשן
console.log('Block:', tx.block_number);
ה-tx_hash מוחזר זהו hash אמיתי על Chain 2027 (או 2026 בסנדבוקס) שניתן לאמת ב-RPC.
הקונסטרקטור:
const tekuna = new Tekuna({
apiKey: 'sk_test_dils_…', // חובה
baseUrl: 'https://api.dils.co.il' // אופציונלי; ברירת המחדל זו
});
tekuna.dilsmint({ amount_agorot, idempotency_key? })הנפקת DILS לארנק מועדון השותף.
const tx = await tekuna.dils.mint({
amount_agorot: 50000, // 500 ש"ח
idempotency_key: 'order-12345', // אופציונלי, 24 שעות
});
// → { tx_hash, amount_agorot, amount_dils, chain_id, block_number, status }
תקרה: 10,000,000 אגורות (100,000 ש"ח) לכל קריאה.
tekuna.endUserslist({ limit?, offset?, kyc_status? })מחזיר את רשימת משתמשי הקצה השייכים לשותף המאומת.
const { users, total } = await tekuna.endUsers.list({
limit: 100,
offset: 0,
kyc_status: 'verified', // 'pending' | 'in_review' | 'verified' | 'rejected'
});
console.log(`${users.length} מתוך ${total} משתמשים`);
get(id)מחזיר משתמש קצה יחיד לפי מזהה.
const user = await tekuna.endUsers.get('user-uuid');
// → { id, email, full_name, phone, wallet_address, kyc_status, kyc_level, created_at }
זורק TekunaApiError עם סטטוס 404 אם המשתמש לא קיים או לא שייך לשותף.
tekuna.walletbalance()תמונת מצב של יתרת DILS + TKN על השרשרת.
const bal = await tekuna.wallet.balance();
// → { club_id, wallet_address, dils_balance: "123.45",
// dils_balance_agorot: 12345, tkn_balance: "0",
// chain_id, block_number }
dils_balance_agorot הוא היחידה השלמה הקנונית — השתמש בו לחישובים פנימיים.
tekuna.transactionslist({ limit?, offset?, from_date?, to_date?, status? })מחזיר את העסקאות של מועדון השותף, החדשות ביותר ראשונות.
const { transactions, total } = await tekuna.transactions.list({
limit: 50,
from_date: '2026-05-01T00:00:00Z',
to_date: '2026-05-25T00:00:00Z',
status: 'confirmed',
});
for (const tx of transactions) {
console.log(tx.tx_hash, tx.amount_dils, tx.snp_nature);
}
tekuna.authme()זהות השותף המאומת.
const me = await tekuna.auth.me();
// → { club_id, club_name, wallet_address, tier, chain, modules, provisioned_at }
if (me.tier === 'starter') { /* … */ }
כל קריאה זורקת TekunaApiError במקרה של תגובה שאינה 2xx (או שגיאת רשת לפני שהבקשה הגיעה לשרת):
import { Tekuna, TekunaApiError } from '@tekuna/sdk-node';
try {
await tekuna.dils.mint({ amount_agorot: 10000 });
} catch (err) {
if (err instanceof TekunaApiError) {
console.error(`[${err.status}] ${err.code}: ${err.message}`);
console.error('Raw body:', err.details);
if (err.status === 401) {
// מפתח לא תקין או שפג תוקפו → רענן מ-Secret Manager
} else if (err.code === 'WALLET_NOT_DEPLOYED') {
// הפרובוז'נינג לא הושלם → חכה או הרץ מחדש
} else if (err.code === 'RPC_UNAVAILABLE') {
// הרשת לא זמינה זמנית → נסה שוב עם backoff אקספוננציאלי
}
}
throw err;
}
קודי שגיאה מרכזיים:
| Code | סטטוס | משמעות |
|---|---|---|
SDK_KEY_REQUIRED |
401 | חסר Authorization Bearer header |
INVALID_SDK_KEY_FORMAT |
401 | פורמט מפתח לא תקין |
SDK_KEY_INVALID |
401 | מפתח לא מוכר או שבוטל |
INVALID_BODY |
400 | body לא עובר Zod validation בצד השרת |
WALLET_NOT_DEPLOYED |
409 | ארנק המועדון עוד לא נפרס על השרשרת |
CONTRACT_PAUSED |
503 | חוזה DILSMasterToken במצב pause |
RPC_UNAVAILABLE |
503 | חיבור ל-Chain 2027/2026 נכשל זמנית |
MINT_FAILED |
500 | טרנזקציית ה-mint נכשלה (revert, gas) |
NETWORK_ERROR |
0 | שגיאת רשת לפני הגעה לשרת (DNS/socket) |
| סנדבוקס (testnet) | פרודקשן (live) | |
|---|---|---|
| תחילית המפתח | sk_test_dils_… |
sk_live_dils_… |
| Chain ID | 2026 | 2027 |
| גישת RPC | דרך ה-proxy המורשה בלבד: api.dils.co.il/api/rpc (14 מתודות מורשות). אין גישת RPC ישירה לשותפים. |
|
| DILS אמיתי? | לא — בדיקה בלבד | כן — 1:1 לש"ח |
| מקבל כסף אמיתי? | לא | כן — עם REGULATOR_ROLE |
המעבר מסנדבוקס לפרודקשן דורש סבב אישור (KYB מלא + סקירת אבטחה). ה-SDK עצמו זהה — רק המפתח משתנה.
תרחיש: עסק קולט תשלום של 49 ש"ח, מנפיק DILS למועדון, ושומר לקוח רישום עם SNP.
import { Tekuna, TekunaApiError } from '@tekuna/sdk-node';
const tekuna = new Tekuna({ apiKey: process.env.TEKUNA_API_KEY! });
async function settlePosCharge(orderId: string, ils: number, merchantId: string): Promise<string> {
const amount_agorot = Math.round(ils * 100);
try {
const tx = await tekuna.dils.mint({
amount_agorot,
idempotency_key: `pos:${orderId}`,
});
console.log(`✓ Order ${orderId} settled: ${tx.tx_hash}`);
return tx.tx_hash;
} catch (err) {
if (err instanceof TekunaApiError && err.code === 'WALLET_NOT_DEPLOYED') {
throw new Error('המתן לסיום הפרוביז\'נינג של המועדון');
}
throw err;
}
}
await settlePosCharge('ord-7891', 49.00, 'rest-001');
dils_) — מפתח + PIN לקוח + חיובEnglish summary: A second, separate credential/route family from the SDK above —
dils_test_…/dils_live_…keys (tabletekuna_partner_api_keys), used to redeem a customer's 4-digit PIN and charge the customer's DILS balance to your merchant card. This is the real clearing path (used by ANIKAN/LiBi in production) — separate fromsk_above, which only mints DILS to your own club wallet.
⚠️ שני מערכי מפתחות נפרדים, אל תערבב ביניהם:
sk_ (סעיף 4 למעלה) | dils_ (הסעיף הזה) | |
|---|---|---|
| מטרה | הנפקת DILS לארנק המועדון שלך | גביית תשלום מלקוח קצה לכרטיס הסוחר שלך |
| טבלה | sdk_api_keys | tekuna_partner_api_keys |
| Header | Authorization: Bearer sk_… | x-partner-api-key (או x-api-key, ראה 10.3) |
dils_test_/dils_live_מפתח סוחר מונפק דרך ops.dils.co.il (פאנל ה-Operator Portal, /sdk) לכרטיס העסק שלך, או ע"י super_admin.
לא ניתן להנפיק אותו דרך /api/sdk/provision (זה מנפיק רק sk_). המפתח מוצג פעם אחת בלבד — שמור אותו מיד.
כל הקריאות הבאות עם x-partner-api-key: dils_test_… אל https://api.dils.co.il/functions/partner-settlement-api:
שלב א — הלקוח (בעל הכרטיס) מייצר קוד בן 4 ספרות ומוסר לך אותו (במציאות — האפליקציה של הלקוח; בסנדבוקס אתה יכול לבחור קוד לצורך בדיקה):
curl -X POST https://api.dils.co.il/functions/partner-settlement-api/sandbox/create-session \
-H 'x-partner-api-key: dils_test_XXXXXXXXXXXX' \
-H 'Content-Type: application/json' \
-d '{"amount": 25, "customer_card_id": "<כרטיס-הסוחר-שלך-uuid>", "pin_code": "1234"}'
# → 200 {"success":true,"pin_code":"1234","ttl_seconds":180,"expires_at":"…","amount":25,"customer_card_id":"…"}
שלב ב — בדוק יתרת סנדבוקס (נטענת אוטומטית ל-₪100 בקריאה הראשונה — אין צורך "להטעין" ידנית):
curl -X POST https://api.dils.co.il/functions/partner-settlement-api/sandbox/balance \
-H 'x-partner-api-key: dils_test_XXXXXXXXXXXX' \
-H 'Content-Type: application/json' \
-d '{"customer_card_id": "<כרטיס-הסוחר-שלך-uuid>"}'
# → 200 {"success":true,"balance_credits":10000,"balance_ils":100}
שלב ג — בבית העסק: מימוש ה-PIN (נועל את הסכום) — ה-PIN הוא כל מה שצריך:
curl -X POST https://api.dils.co.il/functions/partner-settlement-api/escrow \
-H 'x-partner-api-key: dils_test_XXXXXXXXXXXX' \
-H 'Content-Type: application/json' \
-d '{"pin_code": "1234"}'
# → 200 {"success":true,"escrow_id":"esc_…","status":"HELD","amount_locked":2500,"available_balance":75}
הסכום והכרטיס נגזרים בשרת — הסכום מגיע מרשומת ה-PIN עצמה (הוא נקבע כשהקוד נוצר), והכרטיס נגזר מהמפתח שלך (או מ-
terminal_idאם שלחת אחד). אינך צריך לשלוח אותם, וגם לא כל פרמטר אחר.תאימות לאחור מלאה: אם האינטגרציה שלך כבר שולחת
amountו/אוcustomer_card_id— הם עדיין מתקבלים ונבדקים מול רשומת ה-PIN, ואי-התאמה עדיין מוחזרת כ-AMOUNT_MISMATCH/CUSTOMER_CARD_MISMATCHבדיוק כמו קודם. שום אינטגרציה קיימת אינה נשברת; פשוט כבר אין חובה לשלוח אותם. גםterminal_id,channelו-itemsנשארים אופציונליים.אם השותף מחזיק יותר מכרטיס אחד ולא נשלח
terminal_id, השרת לא מנחש — הוא מחזיר שגיאה מפורשת שמבקשתcustomer_card_idאוterminal_id.
שלב ד — סיום החיוב (עם ה-escrow_id משלב ג׳):
curl -X POST https://api.dils.co.il/functions/partner-settlement-api/finalize-charge \
-H 'x-partner-api-key: dils_test_XXXXXXXXXXXX' \
-H 'Content-Type: application/json' \
-d '{"escrow_id": "esc_…"}'
לביטול לפני סיום: POST /functions/partner-settlement-api/cancel עם אותו escrow_id.
לאיפוס יתרת הסנדבוקס בחזרה ל-₪100: POST /functions/partner-settlement-api/sandbox/reset.
/api/merchant/:card_id (אותו מפתח dils_, header שונה)קיים גם endpoint סוחר נפרד (זה שבו ANIKAN/LiBi משתמשים בפרודקשן), עם x-api-key — לא
x-partner-api-key:
curl https://api.dils.co.il/api/merchant/<כרטיס-הסוחר-שלך-uuid>/info \
-H 'x-api-key: dils_test_XXXXXXXXXXXX'
# → 200 { id, business_name, card_status, environment, kyb_status,
# merchant_payment_endpoint, payment_code_endpoint }
ה-payment_code_endpoint המוחזר (/api/user/generate-payment-code) הוא הדרך שבה הלקוח
(לא הסוחר) מייצר קוד תשלום אמיתי מהאפליקציה שלו; ה-merchant_payment_endpoint
(/api/merchant/:card_id/charge) הוא זה שהסוחר קורא לו עם הקוד כדי לגבות.
אותם endpoints בדיוק, עם מפתח dils_live_… — הכרטיס שלך חייב להיות בסביבת PROD ו-KYB מאושר
(נבדק אוטומטית בשרת). הבדל מהותי: אין "טעינה אוטומטית" — יתרת ה-DILS על הכרטיס בפרודקשן היא כסף
אמיתי שמגיע מהלקוחות שמשלמים דרכך, לא מ-seed.
אין שום הבדל באימות בין סנדבוקס לפרודקשן: מפתח API בלבד. אין חתימת HMAC, אין
secret נוסף, ואין header נוסף — בדיוק כמו בסנדבוקס. הקוד שעבד לך בסנדבוקס עובד
בפרודקשן ללא שינוי; מחליפים את המפתח וזהו.
אם האינטגרציה שלך כבר שולחת header של חתימה (
x-tekuna-signature) — היא ממשיכה לעבוד. חתימה תקינה מתקבלת; חתימה שגויה נדחית. פשוט אין יותר חובה לשלוח אחת.
לכל מפתח יש סביבה משלו הרשומה במסד הנתונים (לא נגזרת משם המפתח), ו-CHECK ברמת המסד מוודא שהסביבה הרשומה תואמת את המפתח עצמו. הגבול הוא המסלול:
| מפתח | מותר | נחסם |
|---|---|---|
dils_test_… (סנדבוקס) | נתיבי /sandbox/* וטבלאות הסנדבוקס המבודדות | מסלול הסליקה האמיתי |
dils_live_… (פרודקשן) | מסלול הסליקה האמיתי | נתיבי /sandbox/* |
מותר ורצוי לבדוק בסנדבוקס כרטיס שכבר מוגדר PROD — זו בדיוק דרך ההצטרפות: בודקים עם מפתח סנדבוקס, מאשרים KYB, מעבירים את הכרטיס ל-PROD, מנפיקים מפתח פרודקשן, ומריצים את אותה קריאה בדיוק. מה שמבודד הוא המסלול והנתונים — לא הכרטיס.
English summary: A self-serve faucet for sandbox test credit —
POST /api/client/faucet/claimandGET /api/client/faucet/status. Works with either key lane (sk_test_dils_…ordils_test_…). Grants 5 DILS by default (max 25/claim, 100/24h, 60s cooldown) intopartner_sandbox_balances— sandbox only,is_real=false, never touches the real DILS supply orsovereign_ledger.
עד 02.08.2026, שותף שקיבל מפתח SDK דרך admin.dils.co.il/sdk לא היה יכול לקבל ולו DILS אחד לבדיקה — הפורטל הנפיק מפתח, הראה צעד "קריאה ראשונה", ואז ציפה מהשותף להריץ חיוב על כרטיס עם יתרה אפסית. הדרך היחידה שהייתה קיימת — POST /functions/partner-settlement-api/sandbox/reset — היא הרסנית: מאפסת את כל הכרטיסים תחת המפתח בחזרה ל-₪100 קבוע ומוחקת את כל ה-PINs וה-escrows של אותו מפתח. עכשיו יש faucet אמיתי.
קרדיטים לסליקת סנדבוקס על Chain 2026, נכתבים ל-partner_sandbox_balances — אותה יתרה בדיוק ש-POST /functions/partner-settlement-api/finalize-charge מחייב ממנה. זה מה שמאפשר לחיוב סנדבוקס מקצה-לקצה להצליח בפועל.
זה לא כסף אמיתי:
| רשת | 2026 (סנדבוקס) — לעולם לא Chain 2027 |
is_real | false, נאכף ע"י DB CHECK constraint, לא רק מוסכמה |
| נספר כהכנסה? | לא |
| נוגע באספקת DILS / trust account? | לא |
קרדיט פרודקשן הוא כסף אמיתי מגובה בנק. הוא לעולם לא ניתן אוטומטית — ראה 11.6 למטה.
| כלל | ערך |
|---|---|
| הענקה כברירת מחדל | 5 DILS |
| מקסימום לקריאה | 25 DILS |
| מקסימום ל-24 שעות (per API key) | 100 DILS |
| Cooldown בין קריאות | 60 שניות |
| מפתחות זכאים | סנדבוקס בלבד (sk_test_dils_…, tk_test_…, dils_test_…) |
אותה מדיניות מוחזרת גם ע"י GET /api/client/faucet/status, כך שהאינטגרציה שלך לא צריכה hard-code.
שני ה-endpoints מקבלים כל אחד ממערכי המפתחות — אין צורך לדעת איזו משתי מערכות המפתחות (סעיף 4 מול סעיף 10 למעלה) הנפיקה את המפתח שלך:
Authorization: Bearer sk_test_dils_… (המפתח ש-biz.dils.co.il/sdk מנפיק)x-partner-api-key: dils_test_… (מפתח הסליקה השותף)POST /api/client/faucet/claimcurl -X POST https://api.dils.co.il/api/client/faucet/claim \
-H "Authorization: Bearer $DILS_SANDBOX_KEY" \
-H "Content-Type: application/json" \
-d '{ "amount_dils": 5 }'
amount_dils אופציונלי (ברירת מחדל 5). customer_card_id אופציונלי אם המפתח שלך משויך לכרטיס יחיד, וחובה אם לא.
{
"success": true,
"granted_dils": 5,
"customer_card_id": "00000000-0000-0000-0000-000000000000",
"balance_before_dils": 0,
"balance_dils": 5,
"network": 2026,
"environment": "sandbox",
"is_real": false,
"allowance": { "remaining_24h_dils": 95, "cooldown_seconds": 60 },
"request_id": "…"
}
GET /api/client/faucet/statuscurl https://api.dils.co.il/api/client/faucet/status \
-H "Authorization: Bearer $DILS_SANDBOX_KEY"
מחזיר זכאות, את המדיניות המלאה, כמה המפתח הזה כבר משך ב-24 השעות האחרונות, כמה שניות נשארו ל-cooldown, ואת יתרת הסנדבוקס הנוכחית של כל כרטיס תחת המפתח.
| HTTP | error | משמעות |
|---|---|---|
| 401 | API_KEY_REQUIRED | אין מפתח, או מפתח שאיננו מזהים. |
| 403 | PRODUCTION_KEY_NOT_ELIGIBLE | שלחת מפתח פרודקשן. ה-faucet משרת סנדבוקס בלבד. |
| 403 | CARD_NOT_IN_SCOPE | הכרטיס הזה לא שלך. (בכוונה זהה בין אם הכרטיס קיים או לא — אין existence oracle.) |
| 400 | CUSTOMER_CARD_REQUIRED | המפתח שלך מכסה יותר מכרטיס אחד; ציין איזה לזכות. |
| 400 | INVALID_BODY | amount_dils חסר, לא חיובי, או מעל 25. |
| 429 | COOLDOWN_ACTIVE | פחות מ-60 שניות מהקריאה האחרונה — retry_after_seconds אומר כמה זמן. |
| 429 | DAILY_LIMIT_REACHED | המפתח הזה משך את ה-100 DILS שלו ל-24 השעות המתגלגלות. |
export BASE=https://api.dils.co.il
export KEY=sk_test_dils_… # מ-biz.dils.co.il/sdk
export CARD=… # ה-Customer Card ID שלך
# 1. וידוא שהמפתח עובד
curl -s $BASE/api/client/status -H "Authorization: Bearer $KEY"
# 2. מימון כרטיס הסנדבוקס
curl -s -X POST $BASE/api/client/faucet/claim \
-H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-d '{"amount_dils": 5}'
# 3. בעל הכרטיס מייצר קוד 4 ספרות ב-iam.dils.co.il, ואז אתה מחייב אותו
curl -s -X POST $BASE/api/merchant/$CARD/charge \
-H "x-api-key: $KEY" -H 'Content-Type: application/json' \
-d '{"user_code": "1234", "amount_dils": 1.5}'
# 4. בדיקה מה נשאר
curl -s $BASE/api/client/faucet/status -H "Authorization: Bearer $KEY"
ה-faucet מעניק קרדיטי סליקה. אם אתה צריך ספציפית יתרת ERC-20 על השרשרת בסנדבוקס Chain 2026, זה POST /api/client/dils/mint עם מפתח testnet — הוא מנפיק לארנק המועדון שלך על השרשרת. החל מ-02.08.2026 ה-route הזה דוחה מפתחות פרודקשן (403 PRODUCTION_MINT_NOT_SELF_SERVE) — הנפקת DILS אמיתי על Chain 2027 היא פעולת Treasury מדרגה 3 (Tier-3) ולעולם לא קורית דרך מפתח API.
קרדיט פרודקשן הוא DILS אמיתי מגובה 1:1 בשקלים אמיתיים המוחזקים ב-trust. הוא מונפק רק דרך תהליך treasury מאושר אנושית:
biz.dils.co.il ← אימות עסקי · KYB).יומן ביקורת: כל בקשת claim כותבת שורה append-only אחת ל-public.sdk_faucet_disbursements
(network=2026, environment='sandbox', is_real=false — נאכף ב-CHECK), ושורת sdk.faucet.claim אחת ליומן ביקורת האבטחה. שום דבר לא נכתב ל-sovereign_ledger — קרדיט בדיקה לעולם לא נכנס לספר האמיתי (Iron Rule #2).
תיעוד מלא של ה-REST API: https://api.dils.co.il/health (מחזיר 200 + מטא-דאטה).
לתמיכה: support@dils.co.il.
לבעיות באבטחה (הסביבה בהתאמה ל-SOC 2 ולדרישות NIMBUS 01-2022; אין היום תעודת הסמכה בתוקף): security@dils.co.il.
עודכן: 2026-08-20 · גרסת SDK: 0.1.0 · בהתאמה ל-NIMBUS 01-2022 · me-west1