# AfterPack Cloud API संदर्भ

api.afterpack.dev का wire contract: authentication, batch obfuscation endpoint, limits, rate limits, build का time budget, और वे diagnostic codes जिन्हें client को संभालना होता है।

Source: https://www.afterpack.dev/hi/docs/cloud-api

एक [Pro key](https://www.afterpack.dev/hi/docs/dashboard/api-keys) configure होते ही `@afterpack/core` और हर [framework plugin](https://www.afterpack.dev/hi/docs/frameworks) यह protocol पहले से बोलते हैं: auth, multipart streaming, retries, सब कुछ। इसे तब पढ़ें जब आप कोई custom CI integration जोड़ रहे हों, official packages के बाहर कोई client लिख रहे हों, या किसी ऐसे response को debug कर रहे हों जिसकी आपके tooling को उम्मीद नहीं थी।

## Base URL और versioning

Base URL: **`https://api.afterpack.dev/v1/`**

API का version URL में होता है, और `v1` ही एकमात्र version है। इसके भीतर response fields जोड़े जाते हैं, कभी हटाए या दूसरे अर्थ में इस्तेमाल नहीं किए जाते; कोई breaking change `v2` के रूप में इसके साथ-साथ ship होगा। `GET /v1/version` deployed version और environment लौटाता है, और `GET /` बिना authentication वाला liveness check है।

## Client compatibility

दो वैकल्पिक request headers, जो न होने या malformed होने पर दोनों **ignore किए जाते हैं, कभी `400` नहीं देते** — curl script हो या इन headers से पुराना client, किसी पर भी कोई असर नहीं पड़ता:

| Header | क्या ले जाता है |
|---|---|
| `X-AfterPack-Client-Version` | Installed `@afterpack/core` का npm version, उस पर बने client के लिए। |
| `X-AfterPack-Client` | Call करने वाला package और उसका version, जैसे `afterpack/0.1.0` या `@afterpack/vite/0.1.0`। |

तुलना केवल server-side होती है, `MAJOR.MINOR.PATCH` पर, किसी भी prerelease suffix को नज़रअंदाज़ करते हुए (`0.1.0-rc.3` को `0.1.0` पढ़ा जाता है); ऐसा version जिसे यह server parse नहीं कर सकता, या header का पूरी तरह न होना, हमेशा स्वीकार किया जाता है। जब तक कोई minimum configured है, हर response में `X-AfterPack-Min-Client-Version` होता है, ताकि script बिना इनकार झेले अपनी स्थिति जाँच सके। यह जाँच key auth के ठीक बाद, request body पढ़े जाने से पहले होती है:

- Configured minimum से नीचे: `426 DIAG_CLIENT_UPGRADE_REQUIRED`, `details.minVersion` के साथ।
- Sunset window के दौरान: `410 DIAG_API_SUNSET`।

डिफ़ॉल्ट रूप से इनमें से कोई configured नहीं है। Workspace इन्हें तभी देखता है जब AfterPack इस API के लिए कोई minimum version या sunset date सेट करता है।

Response में एक top-level `notices` array भी हो सकता है: सफल `batch-summary` पर, किसी भी error body पर, और Free-tier telemetry के `202` पर — `{severity, code, message, url?}`, अधिकतम 5, हर `message` 500 characters तक सीमित। अज्ञात `severity` को warning माना जाता है; इसे दिखाने के अलावा कुछ करने की ज़रूरत नहीं है।

## Authentication

दो credentials, और वे एक-दूसरे की जगह इस्तेमाल नहीं हो सकते।

| Credential | Header | यह कहाँ तक पहुँचता है |
|---|---|---|
| **एक Pro API key** | `Authorization: Bearer ap_v1_<...>` | `POST /v1/obfuscate/batch` और `GET /v1/usage`। Key अपना workspace खुद निकाल लेती है, इसलिए कोई workspace id नहीं भेजा जाता। |
| **एक dashboard session** | वह session जो [sign in](https://www.afterpack.dev/hi/docs/dashboard) करने के बाद आपके browser में रहता है | वह सब कुछ जो किसी account को *manage* करता है: keys बनाना, सूचीबद्ध करना और revoke करना, plans, billing, members, projects। एक स्पष्ट `workspaceId` और एक [workspace role](https://www.afterpack.dev/hi/docs/dashboard/workspaces) लेता है। |

Key एक build credential है। यह obfuscate करती है और अपना usage रिपोर्ट करती है, और यह न दूसरी key बना सकती है, न billing पढ़ सकती है, न workspace बदल सकती है। यही सीमा इसका उद्देश्य है: CI में रखी key आपका allowance खर्च कर सकती है, और कुछ नहीं।

Keys `ap_v1_` के बाद 40 base62 characters होती हैं। Key **ठीक एक बार दिखाई जाती है**, बनाते समय। Server-side केवल एक salted HMAC-SHA256 hash रखा जाता है, इसलिए raw key बाद में कभी वापस नहीं मिल सकती, केवल revoke की जा सकती है। इसे [dashboard](https://www.afterpack.dev/hi/docs/dashboard/api-keys) में बनाएँ।

*(Pro cloud build request-flow diagram — see the web page)*

## Endpoints

### `POST /v1/obfuscate/batch`

एकमात्र obfuscation endpoint। एक call एक build है। हर फ़ाइल पूरी होते ही उसका result stream होकर वापस आता है।

**Request**: `multipart/form-data`।

| Part | ज़रूरी | विवरण |
|---|---|---|
| `batch` | हाँ | Batch manifest, एक JSON **string** part के रूप में। |
| हर फ़ाइल का एक part | हाँ | JS source, उस `partName` के तहत जो उसकी manifest entry घोषित करती है। |
| हर source map का एक part | वैकल्पिक | एक upstream source map, उस entry के `sourceMapPartName` के तहत। |

Manifest यह है:

```jsonc
{
  "version": "1",
  "files": [
    {
      "filePath": "assets/app-a1b2c3.js",  // echoed back on the result part
      "partName": "file0",                 // names the form part carrying the source
      "sourceMapPartName": "map0",         // optional
      "config": { "regions": [ /* ... */ ] } // optional, per-file
    }
  ],
  "config": { "preset": "hard", "seed": 42 }, // batch-level EngineConfig
  "git": { "commitSha": "…", "ref": "…" }     // optional build attribution
}
```

Batch-level `config` एक engine config object है: [Configuration](https://www.afterpack.dev/hi/docs/config) पर दी गई हर key, जिसमें [`preset`](https://www.afterpack.dev/hi/docs/config#preset), [`seed`](https://www.afterpack.dev/hi/docs/config#seed) और [`regions`](https://www.afterpack.dev/hi/docs/config#regions) शामिल हैं। `filePath` और `git` manifest-level fields हैं; ऊपर manifest की बनावट देखें।

`filePath` में quote या CR/LF character नहीं हो सकता। इसे result part के `Content-Disposition` में ज्यों का त्यों echo किया जाता है, और malformed path अस्वीकार कर दिया जाता है।

```bash
curl https://api.afterpack.dev/v1/obfuscate/batch \
  -H "Authorization: Bearer ap_v1_xxx" \
  -F 'batch={"version":"1","files":[{"filePath":"dist/app.js","partName":"file0"}],"config":{"preset":"hard"}}' \
  -F file0=@dist/app.js
```

**Response**: `200`, streaming `multipart/mixed` body के साथ। Parts फ़ाइलें पूरी होते ही आते हैं, इसलिए पूरे batch को buffer करने के बजाय हर part आते ही उसे disk पर लिखें:

1. हर फ़ाइल का एक **`obfuscation-result`** part: `{ version, filePath, status, output, outputMap, processingManifest }`। विफलता पर `output` और `outputMap` `null` होते हैं और `processingManifest.diagnostics` कारण बताता है।
2. एक अंतिम **`batch-summary`** part: `{ version, totalFiles, successCount, failureCount, engineVersion, results, totalDurationMs, totalInputBytes, totalOutputBytes }`।

किसी एक फ़ाइल की विफलता batch को नहीं रोकती। बाकी हर फ़ाइल सामान्य रूप से stream होती रहती है, और summary बताती है कि कितनी सफल और कितनी विफल रहीं।

### `GET /v1/usage`

Workspace का usage और allowance। यह management जैसा एकमात्र read है जो key कर सकती है, ताकि कोई CI job अपना बचा हुआ allowance खुद जाँच सके। यह **या तो** एक Pro API key (जो अपना workspace खुद निकाल लेती है) **या** एक dashboard session के साथ `?workspaceId=` स्वीकार करता है।

```jsonc
{
  "tier": "indie",
  "workspace": { "id": "…", "name": "…" },
  "allowance": { "remainingMb": 412.5, "totalMb": 500, "resetAt": "…" },
  "credits": { "balanceMb": 20 },
  "subscription": { "status": "active", "plan": "indie_monthly", "renewsAt": "…", "graceUntil": null, "lapsed": false },
  "recentBuilds": [
    {
      "buildId": "…", "builtAt": "…", "fileCount": 61,
      "totalBytes": 3145728, "outputBytes": 9437184,
      "meteredMb": 3.0, "allowanceMb": 3.0, "creditMb": 0, "overageMb": 0,
      "projectId": "…", "cloudMs": 39120
    }
  ]
}
```

अज्ञात होने पर `outputBytes` और `cloudMs` `null` होते हैं, उनकी जगह कभी `0` नहीं। `allowanceMb` / `creditMb` / `overageMb` तीन pools में `meteredMb` का बँटवारा हैं।

## Limits

| Limit | मान |
|---|---|
| प्रति फ़ाइल | 50 MB |
| प्रति batch फ़ाइलें | 200 |
| Batch के कुल bytes | 500 MB |

इनमें से किसी को भी पार करने पर request पूरी की पूरी `413` और `DIAG_FILE_TOO_LARGE` या `DIAG_BATCH_TOO_LARGE` के साथ अस्वीकार हो जाती है, कुछ भी meter होने से पहले। Dashboard की ओर से यही संख्याएँ [API keys](https://www.afterpack.dev/hi/docs/dashboard/api-keys) में हैं।

## Rate limits

एक rolling **60-second** window पर, प्रति key और प्रति client IP गिने जाते हैं:

| Scope | Limit |
|---|---|
| प्रति key, free workspace | 10 requests / min |
| प्रति key, paid workspace | 100 requests / min |
| प्रति client IP | 100 requests / min |

किसी भी scope को पार करने पर `429` लौटता है, `DIAG_RATE_LIMITED` और एक `Retry-After` header के साथ, जो उस समय पर सेट होता है जब तक trigger करने वाली window वास्तव में खाली न हो जाए। यदि rate-limit check खुद नहीं चल पाता, तो request `503 DIAG_RATE_CHECK_UNAVAILABLE` और `Retry-After: 5` के साथ fail closed होती है।

## Build का time budget

पूरा bundle एक ही invocation के भीतर, **120-second CPU limit** के तहत obfuscate होता है। दो wall-clock budgets build को उस limit के भीतर रखते हैं।

| बीता समय | क्या होता है |
|---|---|
| **45 s** | [Protection Map](https://www.afterpack.dev/hi/docs/protection-map) capture रुक जाता है। Obfuscation पूरा होने तक चलता है; stored map को `deadline` skip reason के साथ partial चिह्नित किया जाता है। |
| **90 s** | कोई नई फ़ाइल *शुरू* नहीं की जाती। बाकी हर फ़ाइल `DIAG_BUILD_DEADLINE` के साथ एक स्पष्ट failure stream करती है, जो बताती है कि N में से कितनी पूरी हुईं, और stream सामान्य रूप से बंद होती है। |

अगर आप दूसरे budget तक पहुँचते हैं, तो batch को बाँट दें।

## Diagnostic codes

Errors HTTP status के साथ एक स्थिर `code` लेकर आते हैं, उसी `DIAG_*` namespace में जिसमें engine के अपने [diagnostics](https://www.afterpack.dev/hi/docs/diagnostics) हैं। जिन्हें client को संभालना होता है:

| Code | Status | अर्थ |
|---|---|---|
| `DIAG_INVALID_KEY` | 401 | Key मौजूद नहीं या पहचानी नहीं गई। |
| `DIAG_KEY_REVOKED` | 401 | Key revoke कर दी गई थी। |
| `DIAG_KEY_EXPIRED` | 401 | Key अपने `expiresAt` से आगे निकल चुकी है। |
| `DIAG_KEY_OUT_OF_SCOPE` | 403 | Key मान्य है, पर उसकी `allowedIPs` सूची के बाहर के IP से इस्तेमाल हुई। |
| `DIAG_CLIENT_UPGRADE_REQUIRED` | 426 | Client configured minimum version से नीचे है। `details.minVersion` साथ आता है। देखें [Client compatibility](#client-compatibility)। |
| `DIAG_API_SUNSET` | 410 | इस API version का sunset हो चुका है। देखें [Client compatibility](#client-compatibility)। |
| `DIAG_ENTITLEMENT_LAPSED` | 402 | Subscription का भुगतान बकाया है। `graceUntil` और `upgradeUrl` साथ आते हैं। |
| `DIAG_QUOTA_EXHAUSTED` | 402 | [Allowance + credits](https://www.afterpack.dev/hi/docs/dashboard/usage) (+ [overage cap](https://www.afterpack.dev/hi/docs/tiers), अगर चालू है) इस build को कवर नहीं कर सकते। `remainingMb`, `requestedMb` और एक `reason` साथ आते हैं, जो "quota ख़त्म" को "overage cap तक पहुँचे" से अलग करता है। |
| `DIAG_RATE_LIMITED` | 429 | ऊपर rate limits देखें। `retryAfterSeconds` साथ आता है। |
| `DIAG_RATE_CHECK_UNAVAILABLE` | 503 | Rate-limit check विफल हुआ; fail closed। Retry करें। |
| `DIAG_INVALID_MANIFEST` | 400 | Malformed multipart body, `batch` part मौजूद नहीं, या ऐसा manifest जो validation में fail होता है। |
| `DIAG_FILE_TOO_LARGE` | 413 | कोई एक फ़ाइल 50 MB से बड़ी। |
| `DIAG_BATCH_TOO_LARGE` | 413 | 200 से ज़्यादा फ़ाइलें या कुल 500 MB से ज़्यादा। |
| `DIAG_BUILD_DEADLINE` | n/a | प्रति फ़ाइल, एक `200` stream के भीतर। इस फ़ाइल के शुरू होने से पहले build का time budget ख़त्म हो गया। |
| `DIAG_ENGINE_FAILURE` | n/a | प्रति फ़ाइल, एक `200` stream के भीतर। इस फ़ाइल पर engine ने error throw किया। |

आख़िरी दो HTTP statuses **नहीं** हैं। वे एक सफल response के भीतर किसी `obfuscation-result` part पर `status: "failure"` के रूप में आते हैं। जो client केवल HTTP status देखता है, वह आंशिक रूप से विफल build को साफ़ build समझ बैठेगा।

## Retries और backoff

| Status | Retry योग्य | व्यवहार |
|---|:---:|---|
| `400`, `401`, `402`, `403`, `413` | नहीं | Request ठीक करें। |
| `429` | एक बार | `Retry-After` का ठीक-ठीक पालन करें, 120 s तक सीमित; दूसरा `429` fail closed होता है। |
| `500` | नहीं | Engine bug; इसे रिपोर्ट करें। |
| `503`, `504` | हाँ | 1 s, 4 s, 16 s (तीन retries, कुल चार प्रयास), फिर fail closed। |

Official client 120-second का whole-request timeout भी लागू करता है, और DNS, TLS तथा connection-reset failures को अनिश्चित काल तक retry करने के बजाय [unreachable-cloud](https://www.afterpack.dev/hi/docs/deployment-modes) मानता है।

## Key lifecycle, client की नज़र से

Keys बनाना, उनका scope तय करना और उन्हें revoke करना [dashboard operations](https://www.afterpack.dev/hi/docs/dashboard/api-keys) हैं। इस API को call करने वाले code के लिए दो व्यवहार मायने रखते हैं:

- **Build के बीच revocation।** Batch stream होते समय revoke की गई key केवल *अगली* request पर `401` लौटाती है; जो कुछ पहले से चल रहा है, वह सामान्य रूप से पूरा होता है।
- **IP सूची तक सीमित key** कहीं और से इस्तेमाल होने पर `403 DIAG_KEY_OUT_OF_SCOPE` लौटाती है, जो अमान्य या revoke की गई key को मिलने वाले `401` से अलग है, ताकि client "गलत key" और "सही key, गलत जगह" में फ़र्क कर सके।

> **Metering atomic है, और यह सबसे पहले चलती है**
>
> जो batch workspace के pools में नहीं समाता, वह किसी भी फ़ाइल के dispatch होने से *पहले* पूरा का पूरा अस्वीकार हो जाता है, और pools अछूते रहते हैं: कभी आंशिक रूप से process नहीं, कभी आंशिक रूप से bill नहीं। यह [fail-closed नियम](https://www.afterpack.dev/hi/docs/diagnostics#fail-closed-no-exceptions) का batch-level रूप है।

## Source code का प्रबंधन

Obfuscation के लिए भेजा गया source **केवल memory में**, उसी एक request की अवधि तक process होता है, और कभी disk, logs या search index में नहीं लिखा जाता। Logs में request ids, फ़ाइलों की गिनती, bytes का योग और diagnostic codes होते हैं, कभी फ़ाइल contents, identifier names या constant values नहीं।

एक artifact request के बाद भी बना रहता है: dashboard के लिए हर build के साथ stored [Protection Map](https://www.afterpack.dev/hi/docs/protection-map)। इसमें आपका मूल source होता है, जो इस आधार पर रंगा होता है कि हर token पर कितना transformation हुआ। यह हर project के लिए डिफ़ॉल्ट रूप से चालू है, केवल मालिक workspace के members ही इसे पढ़ सकते हैं, इसे एक साल **और** प्रति project आख़िरी 500 builds तक रखा जाता है (जो पहले ख़त्म हो), और इसे [project settings](https://www.afterpack.dev/hi/docs/dashboard/workspaces) में बंद किया जा सकता है। पूरा विवरण [Privacy और data handling](https://www.afterpack.dev/hi/docs/privacy) में है।

## आगे

- [Deployment modes](https://www.afterpack.dev/hi/docs/deployment-modes): local Free build की तुलना में यह protocol कहाँ फिट होता है।
- [Pro](https://www.afterpack.dev/hi/docs/pro): Pro local engine के ऊपर क्या जोड़ता है।
- [Privacy और data handling](https://www.afterpack.dev/hi/docs/privacy): क्या stored होता है, कितने समय तक, और उसे कौन पढ़ सकता है।
- [Tiers](https://www.afterpack.dev/hi/docs/tiers): MB allowances, overage, और हर plan इस API पर क्या अनलॉक करता है।
- [API keys](https://www.afterpack.dev/hi/docs/dashboard/api-keys): उस credential को बनाना, उसका scope तय करना, rotate और revoke करना जिसे यह API authenticate करता है।
- [CLI reference](https://www.afterpack.dev/hi/docs/cli): official client जो इन नियमों को लागू करता है।
- [Configuration](https://www.afterpack.dev/hi/docs/config): वह engine config जो `config` field ले जाता है।
