תיעוד API לקיצור קישורים
API רשמי ליצירה ולניהול של קישורים קצרים, תגיות, סטטיסטיקות ומפתחות. כל הדוגמאות אמיתיות ותואמות אחת-לאחת את השרת.
כתובת בסיס ומעטפת תשובות
כל הקריאות נשלחות אל:
https://ktzr.io/api תשובה מוצלחת עטופה תמיד ב-data; שגיאה מוחזרת כ-error עם הודעה קריאה:
{ "data": { ... } } // 2xx
{ "error": "readable message" } // 4xx / 5xx אימות
שתי דרכים להזדהות:
אסימון זיהוי של Firebase (משתמשים מחוברים באפליקציה):
Authorization: Bearer <Firebase ID token> מפתח API (לשרתים ולסקריפטים). מפתחות נוצרים באפליקציה או דרך ה-API, מתחילים תמיד ב-rsvp_live_sk_, ומוצגים פעם אחת בלבד בעת היצירה:
X-API-Key: rsvp_live_sk_... זיהוי סביבת העבודה
כל משאב ב-/api/v1 שייך לסביבת עבודה (workspace). הזיהוי נקבע כך:
- קריאה עם מפתח API פועלת תמיד על סביבת העבודה שהמפתח שייך לה - הפרמטר workspace מתעלם ממנו.
- קריאה עם אסימון זיהוי יכולה לציין ?workspace={slug}; בלעדיו נבחרת סביבת ברירת המחדל של החשבון.
- סביבה שאינה קיימת או שאינכם חברים בה עונה 404 - קיומה לעולם אינו נחשף.
מגבלות קצב ומכסות
- יצירה, עריכה ומחיקה של קישורים חולקות תקציב אחד: 20 פעולות בשעה לכל סביבת עבודה (ברירת מחדל). מעבר לתקציב עונה 429 עם כותרת Retry-After בשניות.
- מכסת קישורים פעילים: 100 קישורים לכל סביבת עבודה (ברירת מחדל); מחיקת קישור מפנה מקום. חריגה עונה 403.
- חשבון חדש: עד 5 קישורים ב-24 השעות הראשונות.
- יצירת קישור מחזירה גם כותרת X-RateLimit-Remaining עם יתרת התקציב השעתי.
- דיווחי שימוש לרעה (ללא הזדהות): עד 5 בשעה לכל כתובת IP.
כל הנתיבים
| מתודה | נתיב | אימות | תיאור |
|---|---|---|---|
| POST | /api/register | אסימון בלבד | רישום החשבון המחובר (גוף אופציונלי: {"tosVersion"}) |
| GET | /api/v1/me | אסימון או מפתח | זהות החשבון וסביבת ברירת המחדל |
| DELETE | /api/v1/me | אסימון בלבד | מחיקת החשבון כולו (עונה 202) |
| POST | /api/v1/workspace | אסימון בלבד | יצירת סביבת עבודה: {"name"?, "slug"?, "tosVersion"?} |
| GET | /api/v1/workspace | אסימון או מפתח | פרטי הסביבה, המסלול והניצול |
| PATCH | /api/v1/workspace | אסימון בלבד | עדכון שם או slug (בעלי הסביבה בלבד) |
| GET | /api/v1/links | אסימון או מפתח | רשימת קישורים עם עימוד וסינון |
| POST | /api/v1/links | אסימון או מפתח | יצירת קישור: {"url", "domain"?, "code"?, "tagIds"?, "temporary"?} |
| GET | /api/v1/links/{code} | אסימון או מפתח | קישור בודד |
| PATCH | /api/v1/links/{code} | אסימון או מפתח | עדכון יעד, יעד זמני או תגיות: {"url"?, "temporary"?, "tagIds"?} |
| DELETE | /api/v1/links/{code} | אסימון או מפתח | מחיקה רכה - הקישור עונה 410 לתמיד |
| GET | /api/v1/links/{code}/history | אסימון או מפתח | עד 50 עריכות יעד אחרונות |
| GET | /api/v1/tags | אסימון או מפתח | רשימת התגיות בסביבה |
| POST | /api/v1/tags | אסימון או מפתח | תגית חדשה: {"name", "color"} |
| PATCH | /api/v1/tags/{id} | אסימון או מפתח | עדכון שם או צבע |
| DELETE | /api/v1/tags/{id} | אסימון או מפתח | מחיקת תגית |
| GET | /api/v1/keys | אסימון בלבד | רשימת המפתחות שלכם בסביבה |
| POST | /api/v1/keys | אסימון בלבד | מפתח חדש: {"name", "permissions"?, "expiresIn"?} |
| PATCH | /api/v1/keys/{keyId} | אסימון בלבד | עדכון שם, הרשאות או השבתה |
| DELETE | /api/v1/keys/{keyId} | אסימון בלבד | ביטול המפתח לצמיתות |
| GET | /api/v1/stats/{code}?days=N | אסימון או מפתח | סך קליקים ופילוח יומי |
| POST | /api/abuse | ללא | דיווח ציבורי על קישור פוגעני |
יצירת קישור
שולחים כתובת, מקבלים קישור קצר. domain אופציונלי (ברירת מחדל ktzr.io, לפי הרשאות החשבון); code - כתובת בהתאמה אישית של 3 עד 50 תווים מתוך [a-zA-Z0-9_-] - זמין כיום לחשבונות מנהל בלבד (מתוכנן ל-Pro); tagIds - עד 10 מזהי תגיות קיימות.
כל יעד נבדק מול Google Web Risk: יעד מסוכן נדחה עם 422.
אפשר לשלוח כבר ביצירה גם temporary, יעד זמני - ההסבר בהמשך.
curl -X POST https://ktzr.io/api/v1/links \
-H "X-API-Key: rsvp_live_sk_..." \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/very/long/path?with=parameters"}' HTTP/2 201
X-RateLimit-Remaining: 19
{
"data": {
"shortCode": "aB3xK9qZ",
"shortUrl": "https://ktzr.io/aB3xK9qZ",
"domain": "ktzr.io",
"tagIds": []
}
} HTTP/2 422
{ "error": "This destination is flagged as unsafe (SOCIAL_ENGINEERING) and cannot be shortened." } רשימת קישורים
עימוד מבוסס-סמן: limit בין 1 ל-100 (ברירת מחדל 25), cursor מהתשובה הקודמת (אטום - לא לפרסר), status אחד מ-active / disabled / deleted (בלי סינון, קישורים שנמחקו אינם מוצגים), tag מזהה תגית, search קידומת של הקוד הקצר. nextCursor הוא null בעמוד האחרון; עמוד יכול להחזיר פחות מ-limit גם כשיש עוד תוצאות - ממשיכים לפי הסמן.
curl "https://ktzr.io/api/v1/links?limit=25&status=active&search=aB" \
-H "Authorization: Bearer <ID token>" {
"data": {
"links": [
{
"shortCode": "aB3xK9qZ",
"shortUrl": "https://ktzr.io/aB3xK9qZ",
"originalUrl": "https://example.com/very/long/path?with=parameters",
"effectiveUrl": "https://example.com/very/long/path?with=parameters",
"temporary": null,
"domain": "ktzr.io",
"status": "active",
"tagIds": ["fJ29xPqLmA31Bc7Yd0Ek"],
"visits": 42,
"botVisits": 7,
"createdAt": "2026-08-30T10:15:00.000Z"
}
],
"nextCursor": null
}
} סטטיסטיקות
סך הקליקים ופילוח יומי (UTC) של הימים האחרונים: days בין 1 ל-90, ברירת מחדל 30. ימים בלי קליקים חוזרים כאפסים. בוטים (תצוגות מקדימות, סורקים, סקריפטים) נספרים בנפרד ב-botVisits.
curl "https://ktzr.io/api/v1/stats/aB3xK9qZ?days=7" \
-H "X-API-Key: rsvp_live_sk_..." {
"data": {
"shortCode": "aB3xK9qZ",
"total": 42,
"botTotal": 7,
"daily": [
{ "date": "2026-08-24", "visits": 5, "botVisits": 1 },
{ "date": "2026-08-25", "visits": 9, "botVisits": 2 }
]
}
} עריכה, מחיקה והיסטוריה
- PATCH מקבל url חדש (נבדק שוב מול Web Risk) או tagIds חדשים. עריכת יעד נרשמת בהיסטוריה.
- DELETE היא מחיקה רכה: הקישור עונה 410 לכל דורש, והקוד לעולם לא ימוחזר. פעולה על קישור שכבר נמחק עונה 410.
- GET /api/v1/links/{code}/history מחזיר עד 50 עריכות יעד, מהחדשה לישנה.
יעד זמני
מפנים קישור ליעד אחר עד מועד שתבחרו, ואחר כך הוא חוזר לבד ליעד הקבוע. שולחים ב-PATCH את temporary עם url ועם until - תאריך ושעה בפורמט ISO 8601 עם אזור זמן (Z או היסט), עד 365 ימים קדימה. היעד הקבוע, originalUrl, אינו משתנה, ועריכה של url אינה נוגעת ביעד הזמני. כדי לסיים אותו מיד שולחים temporary: null.
curl -X PATCH https://ktzr.io/api/v1/links/aB3xK9qZ \
-H "X-API-Key: rsvp_live_sk_..." \
-H "Content-Type: application/json" \
-d '{"temporary": {"url": "https://example.com/tonight", "until": "2027-06-01T08:00:00+03:00"}}' {
"data": {
"shortCode": "aB3xK9qZ",
"shortUrl": "https://ktzr.io/aB3xK9qZ",
"originalUrl": "https://example.com/very/long/path?with=parameters",
"effectiveUrl": "https://example.com/tonight",
"temporary": {
"url": "https://example.com/tonight",
"until": "2027-06-01T05:00:00.000Z",
"active": true
},
"domain": "ktzr.io",
"status": "active",
"tagIds": ["fJ29xPqLmA31Bc7Yd0Ek"],
"visits": 42,
"botVisits": 7,
"createdAt": "2026-08-30T10:15:00.000Z"
}
} בכל משאב של קישור, effectiveUrl הוא היעד שהקישור מפנה אליו כרגע (קישור מושבת או מחוק עונה 410 בכל מקרה), ו-temporary הוא null או אובייקט עם url, until ו-active. גם אחרי שהמועד עבר, היעד הזמני ממשיך להופיע עם active: false.
גם יעד זמני נבדק מול Google Web Risk, ויעד מסוכן נדחה עם 422. הגדרה של יעד זמני נרשמת בהיסטוריה עם kind: temporary ועם until, וסיום ידני של יעד זמני פעיל נרשם עם kind: temporaryEnded. החזרה האוטומטית בתום המועד אינה נרשמת.
תגיות
שם עד 32 תווים, צבע אחד מתוך: red, orange, yellow, green, teal, blue, purple, pink. שם כפול באותה סביבה עונה 409. מחיקת תגית אינה משנה קישורים - המזהה פשוט מסונן מהם בקריאה.
מפתחות API
ניהול מפתחות דורש אסימון זיהוי (מפתח אינו יכול לנהל מפתחות). עד 10 מפתחות פעילים; expiresIn בימים (1 עד 365, אופציונלי); permissions הן canCreate / canRead / canUpdate / canDelete וברירת המחדל של כולן true. DELETE משבית את המפתח (ביטול הרשאה).
דיווח ציבורי על שימוש לרעה
נתיב פתוח ללא הזדהות. reason בין 10 ל-1000 תווים; reporterEmail אופציונלי. התשובה היא תמיד 202 - קיומו של קוד לעולם אינו נחשף. שימו לב: תשובת נתיב זה אינה במעטפת data.
curl -X POST https://ktzr.io/api/abuse \
-H "Content-Type: application/json" \
-d '{"code": "aB3xK9qZ", "reason": "This link leads to a phishing page impersonating a bank"}' HTTP/2 202
{ "message": "Report received" } קודי שגיאה
| קוד | משמעות |
|---|---|
| 400 | קלט לא תקין (כתובת פסולה, פרמטר חסר, cursor שבור) |
| 401 | חסר או פג אסימון / מפתח לא מוכר |
| 403 | אין הרשאה: מכסה מלאה, חשבון מושעה, אימייל לא מאומת, הרשאת מפתח חסרה, או דומיין שלא הוקצה |
| 404 | לא נמצא - כולל משאבים של סביבת עבודה אחרת (קיומם לא נחשף) |
| 409 | התנגשות: קוד/slug/שם תגית תפוסים |
| 410 | הקישור נמחק (הקוד לא ימוחזר) |
| 422 | היעד מסומן כמסוכן ב-Google Web Risk |
| 429 | חריגה ממגבלת קצב - כותרת Retry-After מציינת בעוד כמה שניות לנסות שוב |
דוגמה לשגיאת 403 (מכסה):
HTTP/2 403
{ "error": "You have reached your maximum limit of 100 URLs. Please delete some existing URLs to create new ones." }