الحسابات ومساحات العمل
إنشاء مفتاح API
إنشاء مفتاح وصول شخصي بإمكانات مختارة (agent:operate و agent:publish و agent:engage) وحد workspace_ids اختياري وعمر حتى 365 يوماً؛ يُعاد السر مرة ولا يُقرأ ثانيةً. لا يمنح الوكيل إلا ما يملكه تفويضه حتى 30 يوماً، ويتوقف المفتاح بانتهاء التفويض. يلزم Manage API keys؛ لا يتاح لـ PAT.
POST /identity-api/api-keys/createمراجعة العقد: · sha256:563d2d581da0ad29
نظرة عامة
إنشاء مفتاح وصول شخصي بإمكانات مختارة (agent:operate و agent:publish و agent:engage) وحد workspace_ids اختياري وعمر حتى 365 يوماً؛ يُعاد السر مرة ولا يُقرأ ثانيةً. لا يمنح الوكيل إلا ما يملكه تفويضه حتى 30 يوماً، ويتوقف المفتاح بانتهاء التفويض. يلزم Manage API keys؛ لا يتاح لـ PAT.
يمكن لكل تفويض وكيل أن يملك حتى 25 مفتاحاً نشطاً. الطلبات التي تتجاوز الحد تُعيد API_KEY_GRANT_KEY_LIMIT.
قد يعني نجاح HTTP قبول الطلب لا اكتماله. للعمل الخلفي، احفظ المعرّف المُعاد وتابع العملية نفسها حتى تنتهي. لا يُعدّ المنشور المجدول أوالمقبول منشوراً حتى تأكيد المنصة؛ انتهاء مهلة العميل لا يثبت النتيجة.
المصادقة والأذونات
لا يستخدم الرمز إلا حقوق مالكه. يفحص كل طلب عضوية مساحة العمل وملكية المورد والمساحات المحددة والإمكانات الممنوحة. يغيّر core و full الأدوات المعروضة؛ ولا يمنحان وصولاً.
حقول الطلب
تعني «مطلوب» داخل الكائن الأب والفرع المختار. الحقل الابن المطلوب لا يجعل الأب الاختياري مطلوباً. نُسخت القواعد وأسماء الحقول أدناه من العقد.
| الحقل / الفرع | النوع / مطلوب | القيود |
|---|---|---|
$ | objectمطلوب في العنصر الأب |
|
name | stringمطلوب في العنصر الأب |
|
lifetime_days | integerاختياري / عنصر | الأيام حتى انتهاء المفتاح (1-365، الافتراضي 365). المفتاح الذي ينشئه وكيل مفوّض لا يتجاوز عمره 30 يوماً.
|
capabilities | arrayاختياري / عنصر | ما يُسمح للمفتاح بفعله. الافتراضي operate و publish و engage لمستخدم مسجّل. لا يمنح الوكيل المفوّض إلا ما يتضمنه تفويضه (ولا إدارة المفاتيح أبداً).
|
capabilities[] | stringاختياري / عنصر |
|
workspace_ids | arrayاختياري / عنصر | تقييد المفتاح بهذه المساحات. احذفه لكل مساحة متاحة للمستخدم. يجب أن يحدد المفتاح المقيّد workspace_id للمسارات التي تستخدم النشطة عادةً، ولا يستدعي قراءات المؤسسة الكاملة.
|
workspace_ids[] | stringاختياري / عنصر |
|
scopes | arrayاختياري / عنصر | اسم بديل مهمل لـ capabilities. يُحترم كما هو تماماً؛ وتُتجاهل القائمة الفارغة.
|
scopes[] | stringاختياري / عنصر |
|
idempotency_key | stringاختياري / عنصر | اختياري. أعِد المفتاح نفسه للمحاولة بأمان. يُعرض السر مرة: إذا وجدت المحاولة المفتاح منشأً، تُعيد 409 IDEMPOTENT_REPLAY (يسميه details.existing_key) بدلاً من عرضه. ألغِه وأنشئ آخر بـ idempotency_key جديد.
|
مخطط JSON Schema الكامل
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 80
},
"lifetime_days": {
"default": 365,
"description": "Days until the key expires (1-365, default 365). A key created by a delegated agent never lives longer than 30 days.",
"type": "integer",
"minimum": 1,
"maximum": 365
},
"capabilities": {
"description": "What the key may do. Defaults to operate, publish and engage for a signed-in user. A delegated agent can only grant what its own authorization holds (never key management).",
"minItems": 1,
"maxItems": 3,
"type": "array",
"items": {
"type": "string",
"enum": [
"agent:operate",
"agent:publish",
"agent:engage"
]
}
},
"workspace_ids": {
"description": "Limit the key to these Workspaces. Omit it for every Workspace the user can access. A limited key must name its Workspace (workspace_id) on routes that would otherwise use the active Workspace, and cannot call organization-wide reads.",
"minItems": 1,
"maxItems": 100,
"type": "array",
"items": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
},
"scopes": {
"description": "Deprecated alias of capabilities. It is honoured exactly; an empty list is ignored.",
"maxItems": 3,
"type": "array",
"items": {
"type": "string",
"enum": [
"agent:operate",
"agent:publish",
"agent:engage"
]
}
},
"idempotency_key": {
"description": "Optional. Reuse the same key to retry safely. The secret is shown once: a retry that finds the key already created answers 409 IDEMPOTENT_REPLAY (details.existing_key names it) instead of showing it again. Revoke that key and create a new one with a new idempotency_key.",
"type": "string",
"minLength": 8,
"maxLength": 160,
"pattern": "^[!-~]+$"
}
},
"required": [
"name"
],
"additionalProperties": false
}الاستجابة والاكتمال
رموز نجاح HTTP: 200. عندما تكتمل العملية: synchronous_http_response.
قد يعني نجاح HTTP قبول الطلب لا اكتماله. للعمل الخلفي، احفظ المعرّف المُعاد وتابع العملية نفسها حتى تنتهي. لا يُعدّ المنشور المجدول أوالمقبول منشوراً حتى تأكيد المنصة؛ انتهاء مهلة العميل لا يثبت النتيجة.
تعني «مطلوب» داخل الكائن الأب والفرع المختار. الحقل الابن المطلوب لا يجعل الأب الاختياري مطلوباً. نُسخت القواعد وأسماء الحقول أدناه من العقد.
| الحقل / الفرع | النوع / مطلوب | القيود |
|---|---|---|
$ | objectمطلوب في العنصر الأب | — |
apiKey | objectمطلوب في العنصر الأب | — |
apiKey.id | stringمطلوب في العنصر الأب |
|
apiKey.name | stringمطلوب في العنصر الأب | — |
apiKey.last_4 | stringمطلوب في العنصر الأب | — |
apiKey.scopes | arrayمطلوب في العنصر الأب | — |
apiKey.scopes[] | stringاختياري / عنصر | — |
apiKey.created_at | stringمطلوب في العنصر الأب |
|
apiKey.expires_at | string | nullمطلوب في العنصر الأب | — |
apiKey.expires_atanyOf 1 | stringمطلوب في العنصر الأب |
|
apiKey.expires_atanyOf 2 | nullمطلوب في العنصر الأب | — |
apiKey.last_used_at | string | nullمطلوب في العنصر الأب | — |
apiKey.last_used_atanyOf 1 | stringمطلوب في العنصر الأب |
|
apiKey.last_used_atanyOf 2 | nullمطلوب في العنصر الأب | — |
apiKey.revoked_at | string | nullمطلوب في العنصر الأب | — |
apiKey.revoked_atanyOf 1 | stringمطلوب في العنصر الأب |
|
apiKey.revoked_atanyOf 2 | nullمطلوب في العنصر الأب | — |
apiKey.status | stringمطلوب في العنصر الأب |
|
apiKey.replaces | object | nullمطلوب في العنصر الأب | — |
apiKey.replacesanyOf 1 | objectمطلوب في العنصر الأب | — |
apiKey.replaces.idanyOf 1 | stringمطلوب في العنصر الأب |
|
apiKey.replaces.nameanyOf 1 | stringمطلوب في العنصر الأب | — |
apiKey.replaces.last_4anyOf 1 | stringمطلوب في العنصر الأب | — |
apiKey.replaces.statusanyOf 1 | stringمطلوب في العنصر الأب |
|
apiKey.replacesanyOf 2 | nullمطلوب في العنصر الأب | — |
apiKey.replaced_by | arrayمطلوب في العنصر الأب | — |
apiKey.replaced_by[] | objectاختياري / عنصر | — |
apiKey.replaced_by[].id | stringمطلوب في العنصر الأب |
|
apiKey.replaced_by[].name | stringمطلوب في العنصر الأب | — |
apiKey.replaced_by[].last_4 | stringمطلوب في العنصر الأب | — |
apiKey.replaced_by[].status | stringمطلوب في العنصر الأب |
|
apiKey.capabilities | arrayاختياري / عنصر | — |
apiKey.capabilities[] | stringاختياري / عنصر |
|
apiKey.workspace_ids | array | nullاختياري / عنصر | — |
apiKey.workspace_idsanyOf 1 | arrayاختياري / عنصر | — |
apiKey.workspace_ids[]anyOf 1 | stringاختياري / عنصر |
|
apiKey.workspace_idsanyOf 2 | nullاختياري / عنصر | — |
apiKey.created_by_delegated_grant_id | string | nullاختياري / عنصر | — |
apiKey.created_by_delegated_grant_idanyOf 1 | stringاختياري / عنصر |
|
apiKey.created_by_delegated_grant_idanyOf 2 | nullاختياري / عنصر | — |
secret | stringمطلوب في العنصر الأب |
|
مخطط JSON Schema الكامل
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"apiKey": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"last_4": {
"type": "string"
},
"scopes": {
"type": "array",
"items": {
"type": "string"
}
},
"created_at": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
"expires_at": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
{
"type": "null"
}
]
},
"last_used_at": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
{
"type": "null"
}
]
},
"revoked_at": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
{
"type": "null"
}
]
},
"status": {
"type": "string",
"enum": [
"active",
"expired",
"revoked"
]
},
"replaces": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"last_4": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"active",
"expired",
"revoked"
]
}
},
"required": [
"id",
"name",
"last_4",
"status"
]
},
{
"type": "null"
}
]
},
"replaced_by": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"last_4": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"active",
"expired",
"revoked"
]
}
},
"required": [
"id",
"name",
"last_4",
"status"
]
}
},
"capabilities": {
"type": "array",
"items": {
"type": "string",
"enum": [
"agent:operate",
"agent:publish",
"agent:engage"
]
}
},
"workspace_ids": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
},
{
"type": "null"
}
]
},
"created_by_delegated_grant_id": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
}
},
"required": [
"id",
"name",
"last_4",
"scopes",
"created_at",
"expires_at",
"last_used_at",
"revoked_at",
"status",
"replaces",
"replaced_by"
]
},
"secret": {
"type": "string",
"minLength": 1
}
},
"required": [
"apiKey",
"secret"
]
}الأخطاء وإعادة المحاولة بأمان
افحص حالة HTTP والجسم. قد يحوي خطأ التحقق 400 ZodError؛ تستخدم أخطاء المعالج error و message و code. احتفظ بـ request_id أو x-request-id للتشخيص دون اعتماد. أصلح أخطاء وصول 401/403 قبل المحاولة واتّبع Retry-After لـ 429. لكتابة غير مؤكدة أو 5xx، اقرأ الموجود أولاً. أعِد مفتاح منع التكرار حيث يُدعم فقط؛ تختلف المحاولة حسب العملية ولا تضمن التسليم مرة واحدة بالضبط.
دليل استكشاف الأخطاء وإصلاحهاأمثلة
تستخدم الأمثلة قيماً خيالية مفحوصة بالمخططات. استبدل المعرّفات بالمفوّض لك، والوسائط بأصول جاهزة، والتواريخ بوقت نشر مؤكد. افحص أهلية الحساب قبل الكتابة. لا تُرسل الصفحة طلبات API.
اضبط SOSOAPI_ACCESS_TOKEN على خادمك ببيانات اعتماد تقبلها العملية، وأبقِه خارج شيفرة المتصفح. للوكيل، استخدم sosoapi auth login للدخول بالمتصفح ودع CLI يحدّث بيانات اعتماده.
request.json
{
"name": "example"
}cURL
curl --request POST \
"https://gqeshlawtcexsapabaui.supabase.co/functions/v1/identity-api/api-keys/create" \
-H "Authorization: Bearer $SOSOAPI_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @request.jsonJavaScript
// Server-side JavaScript. Do not print tokens or credential-bearing responses.
const token = process.env.SOSOAPI_ACCESS_TOKEN;
if (!token) throw new Error("Set an accepted credential for this operation");
const response = await fetch("https://gqeshlawtcexsapabaui.supabase.co/functions/v1/identity-api/api-keys/create", {
method: "POST",
headers: { "Content-Type": "application/json", Authorization: "Bearer " + token },
body: JSON.stringify({
"name": "example"
})
});
const result = await response.json();
// Check response.ok, the operation-specific body and completion state before continuing.CLI
npx sosoapi api post /identity-api/api-keys/create < request.jsonمثال استجابة اصطناعية
{
"apiKey": {
"id": "11111111-1111-4111-8111-111111111111",
"name": "example",
"last_4": "example",
"scopes": [],
"created_at": "2099-01-15T09:00:00Z",
"expires_at": null,
"last_used_at": null,
"revoked_at": null,
"status": "active",
"replaces": null,
"replaced_by": []
},
"secret": "example"
}