REST API पाइपलाइन, स्क्रिप्ट और ऐसी किसी भी चीज़ के लिए है जो एजेंट नहीं है। यदि आप इसके बजाय कोई मॉडल जोड़ रहे हैं, तो MCP server का उपयोग करें — यह समान अनुमति मॉडल पर टूल के रूप में समान ऑपरेशन प्रदर्शित करता है।
Base URL
fastsite स्व-होस्टेड है, इसलिए base URL आपका अपना इंजन होस्ट है। सब कुछ एक ही ओरिजिन के अंतर्गत है: डैशबोर्ड, API, MCP एंडपॉइंट और इनबाउंड वेबहुक।
https://your-host/api/v1 प्रमाणीकरण
हर अनुरोध एक हेडर में API key ले जाता है। इस सतह पर कोई bearer token और कोई सेशन नहीं है — bearer auth MCP के लिए है।
X-API-Key: fs_<key_id>_<secret> एक key 44 अक्षरों की स्ट्रिंग है: शाब्दिक उपसर्ग fs_, 8 अक्षरों की पब्लिक ID, एक अंडरस्कोर और 32 अक्षरों का सीक्रेट। सीक्रेट को argon2id से हैश करके संग्रहीत किया जाता है और केवल एक बार दिखाया जाता है, जब key बनाई जाती है।
php bin/fastsite key:create you@example.com \
--name="Deploy pipeline" \
--scopes=content:write,media:write,publish \
--sites=blog हर साइट की अनुमति देने के लिए --sites=* का उपयोग करें। Keys को डैशबोर्ड से भी प्रबंधित किया जा सकता है, और किसी भी समय रोटेट या रद्द किया जा सकता है — एक रद्द की गई key कैश विंडो के अंत में नहीं बल्कि तुरंत काम करना बंद कर देती है।
हर विफलता एक जैसी दिखती है
एक गुम हेडर, एक खराब key, एक अज्ञात key, एक गलत सीक्रेट, एक रद्द की गई key, और एक निष्क्रिय उपयोगकर्ता — सभी एक ही संदेश के साथ एक ही 401 लौटाते हैं। यह जानबूझकर है — इसका मतलब है कि किसी key के अस्तित्व की जाँच नहीं की जा सकती।
रिस्पॉन्स एनवेलप
हर JSON रिस्पॉन्स की एक ही संरचना होती है, ताकि एक क्लाइंट एक ही फ़ील्ड पर ब्रांच कर सके।
{ "success": true, "data": { … } }
{ "success": false, "error": { "message": "…" } } लिस्ट एंडपॉइंट data के साथ एक pagination ब्लॉक जोड़ते हैं, और data किसी ऑब्जेक्ट की बजाय एक साधारण ऐरे है:
{
"success": true,
"data": [ … ],
"pagination": { "total": 42, "page": 1, "per_page": 20, "total_pages": 3 }
} दो एंडपॉइंट जानबूझकर एनवेलप को तोड़ते हैं, क्योंकि उन्हें रैप करना बेकार होगा: एक शेल फ़ाइल पढ़ने पर text/plain के रूप में रॉ बाइट्स मिलते हैं, और उसे हटाने पर बिना बॉडी के 204 मिलता है।
एक पोस्ट बनाएं, फिर प्रकाशित करें
curl -X POST https://your-host/api/v1/sites/blog/content \
-H "X-API-Key: $FASTSITE_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 2f1c9a7e-…" \
-d '{
"type": "post",
"title": "Hello, world",
"body_html": "<p>Shipped in a single call.</p>",
"status": "published"
}' कंटेंट लिखने से वह प्रकाशित नहीं होता। दोनों जानबूझकर अलग ऑपरेशन हैं — एक पाइपलाइन जितना चाहे बना सकती है, संशोधित कर सकती है और सुधार कर सकती है, बिना किसी चीज़ के विजिटर तक पहुँचे। जब कंटेंट तैयार हो, तो साइट प्रकाशित करें:
curl -X POST https://your-host/api/v1/sites/blog/publish \
-H "X-API-Key: $FASTSITE_KEY"
# → { "success": true, "data": { "job": "0f3c…" } } यह एक job ID के साथ 202 लौटाता है; बिल्ड कतार पर चलता है। परिणाम के लिए GET /api/v1/jobs/0f3c… पोल करें।
title ही क्रिएट पर एकमात्र आवश्यक फ़ील्ड है। type का डिफ़ॉल्ट post है, status का डिफ़ॉल्ट draft है, और जब आप slug नहीं भेजते तो slug शीर्षक से निर्धारित होता है। यदि वह slug पहले से लिया हुआ है, तो इंजन एक काउंटर जोड़कर वास्तव में उपयोग किया गया slug लौटाता है — मान लेने की बजाय हमेशा उसे वापस पढ़ें।
एंडपॉइंट
कंटेंट
| Method | Path | Scope |
|---|---|---|
| GET | /sites/{site}/content | content:read |
| POST | /sites/{site}/content | content:write |
| GET | /sites/{site}/content/{id} | content:read |
| PATCH | /sites/{site}/content/{id} | content:write |
| DELETE | /sites/{site}/content/{id} | content:write |
| GET | /sites/{site}/content/trash | content:read |
| POST | /sites/{site}/content/{id}/restore | content:write |
| DELETE | /sites/{site}/content/{id}/purge | content:write |
| POST | /sites/{site}/content/{id}/fact-check | content:read |
हटाना एक सॉफ्ट डिलीट है — आइटम ट्रैश में जाता है और पुनर्स्थापित किया जा सकता है। purge अपरिवर्तनीय है।
मीडिया
| Method | Path | Scope |
|---|---|---|
| GET | /sites/{site}/media | media:read |
| POST | /sites/{site}/media | media:write |
| DELETE | /sites/{site}/media/{id} | media:write |
| POST | /sites/{site}/media/{id}/restore | media:write |
| DELETE | /sites/{site}/media/{id}/purge | media:write |
अपलोड या तो file नाम के फ़ील्ड के साथ multipart फ़ॉर्म स्वीकार करता है, या fetch के लिए url के साथ JSON। दोनों नहीं — यदि कोई फ़ाइल मौजूद है तो URL को अनदेखा किया जाता है।
curl -X POST https://your-host/api/v1/sites/blog/media \
-H "X-API-Key: $FASTSITE_KEY" \
-F file=@hero.jpg \
-F alt="Sunrise over the harbour" इमेज के लिए alt text आवश्यक है जब तक आप स्पष्ट रूप से decorative=true नहीं पास करते। यह शैली की प्राथमिकता नहीं है — एक गुम alt बिल्ड ऑडिट में विफल होता है, इसलिए API इसे बाद में प्रकाशन में समस्या उत्पन्न करने देने की बजाय पहले ही अस्वीकार कर देता है। URL इम्पोर्ट SSRF-गार्डेड हैं: प्राइवेट एड्रेस रेंज अस्वीकार किए जाते हैं, रीडायरेक्ट पुनः-सत्यापित किए जाते हैं, और डाउनलोड बाइट-कैप्ड होता है।
लाइब्रेरी को ?kind=image,video,file से फ़िल्टर करें। इमेज और वीडियो वेरिएंट पाइपलाइन से गुज़रते हैं; बाकी सब कुछ डाउनलोड योग्य फ़ाइल के रूप में संग्रहीत होता है।
Shell
| Method | Path | Scope |
|---|---|---|
| GET | /sites/{site}/shell/files | shell:read |
| GET | /sites/{site}/shell/file/{path} | shell:read |
| PUT | /sites/{site}/shell/file/{path} | shell:write |
| DELETE | /sites/{site}/shell/file/{path} | shell:write |
| POST | /sites/{site}/shell/snapshot | shell:write |
| POST | /sites/{site}/shell/restore/{rev} | shell:write |
बॉडी फ़ाइल है, JSON नहीं। कोई रैपर ऑब्जेक्ट नहीं है और कोई फ़ील्ड नाम नहीं है — आप बाइट्स भेजते हैं और बाइट्स वापस पाते हैं।
curl -X PUT https://your-host/api/v1/sites/blog/shell/file/templates/base.html.twig \
-H "X-API-Key: $FASTSITE_KEY" \
--data-binary @base.html.twig पाथ में स्लैश हो सकते हैं। राइट्स shell डायरेक्टरी तक सीमित हैं, 5 MB पर कैप्ड हैं, और एक एक्सटेंशन अनुमति सूची तक सीमित हैं (twig, css, js, json, woff2, svg, और सामान्य इमेज प्रकार)। कंटेंट के विपरीत, एक shell राइट रीबिल्ड कतार में डालता है — डिज़ाइन बदल गया, इसलिए आउटपुट को भी बदलना होगा। संपादनों का एक बर्स्ट प्रति फ़ाइल एक बिल्ड की बजाय एक ही बिल्ड में समेकित होता है।
जोखिम भरे बदलाव से पहले स्नैपशॉट लें। पुनर्स्थापित करने पर पहले एक स्नैपशॉट लिया जाता है, इसलिए एक रिस्टोर स्वयं भी पूर्ववत किया जा सकता है।
कंपोनेंट, रीडायरेक्ट, स्क्रिप्ट
| Method | Path | Scope |
|---|---|---|
| PUT | /sites/{site}/components/{handle} | components:write |
| GET · POST | /sites/{site}/redirects | sites:read · sites:write |
| DELETE | /sites/{site}/redirects/{id} | sites:write |
| GET · POST | /sites/{site}/scripts | sites:read · sites:write |
| DELETE | /sites/{site}/scripts/{id} | sites:write |
एक कंपोनेंट {type: "html"|"react", source_code, css?, variables_schema?} है। React अपलोड के समय कंपाइल होता है, इसलिए एक टूटा हुआ कंपोनेंट बाद में टूटे पेज की बजाय आपके अनुरोध पर 422 होता है।
भाषाएं, प्रकाशन, साइट
| Method | Path | Scope |
|---|---|---|
| POST | /sites/{site}/languages | translations:manage |
| DELETE | /sites/{site}/languages/{locale} | translations:manage |
| POST | /sites/{site}/publish | publish |
| GET | /jobs/{uuid} | jobs:read |
| GET | /sites | sites:read |
| POST | /sites | admin |
| PATCH | /sites/{site} | sites:write |
| GET · POST | /sites/{site}/webhooks | sites:read · sites:write |
| GET | /sites/{site}/webhooks/{id}/deliveries | sites:read |
| DELETE | /sites/{site}/webhooks/{id} | sites:write |
| GET | /authoring-guide | sites:read |
| GET | /sites/{site}/authoring-guide | sites:read |
पहले authoring guide प्राप्त करें
GET /api/v1/authoring-guide body HTML, इमेज एम्बेडिंग और shell कॉन्ट्रैक्ट के लिए मशीन-पठनीय नियम लौटाता है। एक साइट पास करने पर उसके locale और एम्बेड सिंटैक्स भी शामिल मिलते हैं। यही वह अंतर है जो कंटेंट को बिल्ड करने योग्य और ऑडिट में अस्वीकृत होने योग्य बनाता है।
Scope
Keys और OAuth ग्रांट एक ही scope शब्दावली साझा करते हैं, इसलिए एक एंडपॉइंट और एक टूल एक्सेस को समान रूप से लागू करते हैं।
| Scope | अनुमति देता है |
|---|---|
sites:read | साइट और उनकी सेटिंग देखें |
sites:write | साइट सेटिंग, रीडायरेक्ट, स्क्रिप्ट, वेबहुक बदलें |
content:read | पोस्ट और पेज पढ़ें |
content:write | पोस्ट और पेज बनाएं और संपादित करें |
media:read | मीडिया लाइब्रेरी देखें |
media:write | इमेज, वीडियो और फ़ाइलें अपलोड करें |
components:write | कंपोनेंट बनाएं और अपडेट करें |
shell:read | टेम्पलेट और थीम पढ़ें |
shell:write | टेम्पलेट और थीम संपादित करें |
translations:manage | locale और अनुवाद प्रबंधित करें |
publish | बिल्ड और प्रकाशित करें |
jobs:read | बिल्ड और job स्टेटस पढ़ें |
backup:read · backup:run · backup:restore | बैकअप ऑपरेशन |
admin | सब कुछ |
केवल admin किसी और चीज़ का तात्पर्य रखता है। कोई read/write पदानुक्रम नहीं है — content:write content:read प्रदान नहीं करता, इसलिए यदि आपको दोनों की आवश्यकता है तो दोनों माँगें। Keys एक साइट सूची से भी पिन होती हैं, और उस सूची के बाहर किसी साइट के लिए अनुरोध हैंडलर तक पहुँचने से पहले ही अस्वीकार कर दिया जाता है।
Idempotency
किसी भी POST पर Idempotency-Key हेडर भेजें और इंजन उसके विरुद्ध परिणाम रिकॉर्ड करता है।
- समान method, path और body के साथ वही key संग्रहीत रिस्पॉन्स दोहराती है, उस पर
Idempotency-Replayed: trueके साथ। - भिन्न body के साथ वही key
422है — यही वह तरीका है जिससे आपको पता चलता है कि आपके retry लॉजिक ने payload बदल दिया। - एक retry जो पहले वाले के चलते रहने के दौरान आती है, उसे
409औरRetry-Afterमिलता है। - यदि हैंडलर थ्रो करता है, या रिस्पॉन्स
5xxया429है, तो key रिलीज़ हो जाती है ताकि एक वास्तविक retry सफल हो सके।
अन्य method हेडर को पूरी तरह अनदेखा करते हैं।
दर सीमाएं
दो फिक्स्ड-विंडो सीमाएं, दोनों प्रति मिनट: प्रति IP 60 अनुरोध और प्रति API key 120। किसी भी को पार करने पर Retry-After के साथ 429 मिलता है। प्रति-IP बकेट वह है जिससे आप आमतौर पर पहले मिलेंगे, क्योंकि एक ही क्लाइंट एक ही एड्रेस है।
JSON अनुरोध बॉडी 4 MiB पर कैप्ड हैं। अपलोड उस जाँच से मुक्त हैं और प्रति-प्रकार मीडिया सीमाओं द्वारा सीमित हैं।
स्टेटस कोड
| कोड | अर्थ |
|---|---|
| 200 · 201 · 202 · 204 | सफलता। 202 का अर्थ है कतारबद्ध — job पोल करें। |
| 401 | गुम, खराब, अज्ञात या रद्द की गई key। |
| 403 | वैध key, लेकिन scope या साइट की अनुमति नहीं है। |
| 404 | ऐसा कोई रूट, साइट या रिकॉर्ड नहीं। |
| 409 | डुप्लिकेट, या एक idempotent अनुरोध अभी भी प्रगति में है। |
| 413 | बॉडी सीमा से अधिक। |
| 422 | सत्यापन विफल — error.message पढ़ें। |
| 429 | दर सीमित। |
निर्माण से पहले जानने योग्य विवरण
- टाइमस्टैम्प सख्त हैं।
scheduled_atऔरpublished_atYYYY-MM-DDTHH:MM:SSZहोने चाहिए — UTC, अपरकेसT, अंत मेंZ।+02:00जैसे ऑफसेट कन्वर्ट करने की बजाय अस्वीकार किए जाते हैं। - स्टेटस मान
draft,scheduled,publishedऔरarchivedहैं। शेड्यूलिंग के लिएscheduled_atआवश्यक है, और समय आने पर शेड्यूलर इसे आपके लिए प्रकाशित करता है। - पेजिंग
?page=और?per_page=है, डिफ़ॉल्ट 20 और अधिकतम 100। - Body HTML हर पाथ पर सैनिटाइज़ होता है। इनलाइन स्टाइल हटाए जाते हैं, स्क्रिप्ट और iframe हटाए जाते हैं, और परिणाम
warningsऐरे के साथ वापस आता है। कंटेंट समस्याएं आपके अनुरोध को कभी विफल नहीं करतीं — वे रिपोर्ट की जाती हैं, सामान्य की जाती हैं और प्रकाशित होती हैं। - कुछ चीजें REST पर नहीं हैं। बैकअप, टीम और API-key प्रबंधन CLI और डैशबोर्ड ऑपरेशन हैं; बैकअप और रिस्टोर MCP पर भी उपलब्ध हैं।
आगे: एजेंट-संचालित प्रकाशन के लिए MCP server, या किसी अपस्ट्रीम सिस्टम से कंटेंट पुश करने के लिए webhooks।