API referenceממשק API

Two surfaces, deliberately separated. Everything you would build against lives under /v1 and is described by a generated OpenAPI document. The Turborepo remote cache lives outside it, on purpose, and this page explains why.

שני משטחים, מופרדים בכוונה. כל מה שתבנו מולו נמצא תחת /v1 ומתואר במסמך OpenAPI שנוצר אוטומטית. המטמון המרוחק של Turborepo נמצא מחוץ לו, בכוונה, והעמוד הזה מסביר למה.

Base URL and authenticationכתובת בסיס ואימות

https://api.shipyard1.comBase URL for every route on this page.כתובת הבסיס לכל נתיב בעמוד הזה.
Authorization: BearerAn sy_live_… API key. This is the path for the CLI, the SDK, CI and agents.מפתח API מסוג sy_live_…. זה המסלול ל-CLI, ל-SDK, ל-CI ולסוכנים.
shipyard_sessionSigned HttpOnly cookie. Used by the web panel only. Do not try to obtain one programmatically.עוגייה חתומה מסוג HttpOnly. בשימוש הפאנל בלבד. אל תנסו להשיג אותה תכנותית.
terminal
curl -sS https://api.shipyard1.com/v1/projects \
  -H "Authorization: Bearer $SHIPYARD_API_KEY" | jq

The generated document is the contractהמסמך הנוצר הוא החוזה

GET /openapi.json is generated from the route definitions themselves, not maintained by hand, so it cannot drift from the implementation. Schemas are zod, compiled by fastify-type-provider-zod, which means the same declaration validates the request and produces the documentation. Anything in that document is a promise under your frame. The SDK is generated from it too.

GET /openapi.json נוצר מהגדרות הנתיבים עצמן, לא מתוחזק ידנית, ולכן הוא לא יכול לסטות מהמימוש. הסכמות הן zod, מהודרות על ידי fastify-type-provider-zod, כלומר אותה הצהרה מאמתת את הבקשה ומייצרת את התיעוד. כל מה שבמסמך הזה הוא הבטחה תחת המסגרת שלכם. גם ה-SDK נוצר ממנו.

One error envelopeמעטפת שגיאה אחת

Every failure on every route, without exception:

כל כישלון בכל נתיב, ללא יוצא מן הכלל:

response
{
  "error": {
    "code": "not_found",
    "message": "Not found",
    "request_id": "req_01J91TTB2P4Q"
  }
}

request_id echoes your x-request-id header when you send a sane one, and is generated otherwise. Put it in your support mail and we can find the request without asking you twenty questions.

request_id מחזיר את כותרת x-request-id ששלחתם אם היא תקינה, ואחרת נוצר אוטומטית. שימו אותו בפנייה לתמיכה ונוכל למצוא את הבקשה בלי לשאול אתכם עשרים שאלות.

404 is deliberately ambiguous404 מעורפל בכוונה

“Does not exist” and “exists but is not yours” return the identical status, body and headers. That is not sloppiness; distinguishing them would turn the API into an enumeration oracle for other tenants’ resource ids. There is a single notFound() helper for this reason, and constructing a different not-found response anywhere in the codebase is treated as a bug.

”לא קיים“ ו”קיים אבל לא שלך“ מחזירים סטטוס, גוף וכותרות זהים. זו לא רשלנות; הבחנה ביניהם הייתה הופכת את ה-API לאורקל לספירת מזהי משאבים של דיירים אחרים. בדיוק לשם כך יש פונקציית notFound() אחת, ובניית תשובת not-found אחרת בכל מקום בקוד נחשבת באג.

Core routesנתיבים מרכזיים

GET /v1/whoamiOrg, role and scopes for the presented credential.ארגון, תפקיד והרשאות של האישור שהוצג.
GET /v1/projectsProjects visible to this credential.הפרויקטים הגלויים לאישור הזה.
POST /v1/projectsCreate a project.יצירת פרויקט.
GET /v1/projects/:idOne project with its current releases.פרויקט אחד עם השחרורים הנוכחיים שלו.
POST /v1/deploymentsStart a deployment. Returns a dep_… immediately.התחלת פריסה. מחזיר dep_… מיד.
GET /v1/deployments/:idStatus, timings and scan verdict.סטטוס, זמנים ופסיקת סריקה.
GET /v1/deployments/:id/logsBuild and runtime logs. Supports streaming.לוגים של בנייה וריצה. תומך בזרימה.
POST /v1/deployments/:id/rollbackPromote a previous release.קידום שחרור קודם.
GET /v1/projects/:id/envVariable names and metadata. Never values.שמות משתנים ומטא-דאטה. לעולם לא ערכים.
PUT /v1/projects/:id/env/:nameSet a variable.הגדרת משתנה.
GET /v1/projects/:id/domainsHostnames with TLS state.שמות מארח עם מצב TLS.
GET /v1/auditAudit events, filterable by actor and time.אירועי ביקורת, ניתנים לסינון לפי מבצע וזמן.

The remote cache: /v8/artifactsהמטמון המרוחק: /v8/artifacts

Five routes that sit outside /v1 and are hidden from the OpenAPI document, which also excludes them from SDK generation. That is an exception to everything above and it is intentional.

חמישה נתיבים שיושבים מחוץ ל-/v1 ומוסתרים ממסמך ה-OpenAPI, מה שגם מוציא אותם מייצור ה-SDK. זהו חריג לכל מה שלמעלה, והוא מכוון.

GET /v8/artifacts/statusenabled | disabled | over_limit | pausedenabled | disabled | over_limit | paused
HEAD /v8/artifacts/:hashExistence and size, no body.קיום וגודל, ללא גוף.
GET /v8/artifacts/:hashArtifact bytes, application/octet-stream.בתי הפריט, application/octet-stream.
PUT /v8/artifacts/:hashStreamed upload, 202 on success.העלאה בזרימה, 202 בהצלחה.
POST /v8/artifacts/eventsClient telemetry. Always 200.טלמטריה מהלקוח. תמיד 200.
.turbo/config.json or env
TURBO_API=https://api.shipyard1.com
TURBO_TOKEN=sy_live_xxxxxxxxxxxxxxxxxxxx
TURBO_TEAM=your-org-slug

Tenancyהפרדת דיירים

An artifact is addressed by (org_id, hash) and by nothing the client sends. teamId and slug arrive as query parameters and are treated as untrusted hints: they are compared against the authenticated key’s org, and a mismatch returns the same 404 as a nonexistent hash. Two organisations building the same open-source dependency legitimately produce the same hash and each must read back its own bytes, so uniqueness is on the pair, never on the hash alone.

פריט ממוען לפי (org_id, hash) ולפי שום דבר שהלקוח שולח. teamId ו-slug מגיעים כפרמטרי שאילתה ומטופלים כרמזים לא אמינים: הם מושווים לארגון של המפתח המאומת, ואי-התאמה מחזירה את אותו 404 כמו hash שלא קיים. שני ארגונים שבונים את אותה תלות קוד פתוח מייצרים באופן לגיטימי את אותו hash וכל אחד חייב לקרוא את הבתים של עצמו, ולכן הייחודיות היא על הזוג, לעולם לא על ה-hash לבדו.

Rate limitsמגבלות קצב