{"id":67581,"plugin_id":"plugin_asdk_app_6ac7b1a0689c81919b1b49bfa1eb5a9d","kind":"skill","collection_source":"plugin_package","comparison_source":null,"observed_at":"2026-10-28T13:09:36.141Z","digest":"923e1a39ac52cadb4f38492c50d7219ee096a05c4810d42fa022c733e80dd0ab","against":null,"payload":{"description":"Use when implementing, refactoring, or reviewing `@crowdin/crowdin-api-client` usage in any JavaScript or TypeScript project, especially for endpoint selection, request/response typing, pagination, uploads, retries, timeouts, or `CrowdinError` handling.","included_files":[{"relative_path":"references/recipes.md","size_in_bytes":25489}],"name":"crowdin-api-client","skill_md_contents":"---\nname: crowdin-api-client\ndescription: Use when implementing, refactoring, or reviewing `@crowdin/crowdin-api-client` usage in any JavaScript or TypeScript project, especially for endpoint selection, request/response typing, pagination, uploads, retries, timeouts, or `CrowdinError` handling.\n---\n\n# Crowdin API Client\n\n## Overview\n\nUse this skill when touching Crowdin API integration code in any project that depends on `@crowdin/crowdin-api-client`.\nCore principle: verify local client typings first, then implement with strict model types and correct response envelope handling.\n\n## When to Use\n\n- New or changed calls to `@crowdin/crowdin-api-client`.\n- Compile/type errors after API-client upgrades.\n- Confusion about method names, request fields, or `ResponseList` vs `ResponseObject`.\n- Refactors involving uploads, file translations, screenshots, tasks, comments, strings, or projects.\n- Reviews where behavior works at runtime but types/mapping look suspicious.\n- Multi-step flows: build and download, pre-translate, upload or update files, label strings and open a task, TM or glossary import, reports. Start from [references/recipes.md](references/recipes.md) instead of composing the calls from memory.\n\nDo not use this skill for unrelated infra-only changes.\n\n## Required Preflight (Before Editing)\n\n1. Check local declarations first: `node_modules/@crowdin/crowdin-api-client/out/<module>/index.d.ts`.\n2. Confirm exact API class and method name in use.\n3. Confirm request model type and required fields.\n4. Confirm response envelope: `ResponseList<T>` or `ResponseObject<T>`.\n\nDo not code from memory when typings and docs disagree.\n\n## Quick Reference\n\n| Scenario | Preferred Pattern |\n|---------|-------------------|\n| Multi-module flow | `new Client(credentials, options)` and destructure needed APIs |\n| Single narrow flow | Direct module API class is acceptable |\n| Full collection reads | `.withFetchAll()` |\n| Transient failures | `retryConfig` |\n| Bounded request duration | `{ httpRequestTimeout: 60_000 }` |\n| Uploads | `uploadStorageApi.addStorage` -> `sourceFilesApi.createFile` |\n| Long-running operations (builds, pre-translation, imports, exports, reports) | Poll the matching `check...Status` method with a delay; stop on `finished`, `failed` or `canceled` — [recipes](references/recipes.md#helpers-wait-save-chunk) |\n| Error branching | `CrowdinValidationError` before `CrowdinError` |\n\n## Core Patterns\n\n### Bootstrap\n\n```ts\nimport { Client, Credentials } from '@crowdin/crowdin-api-client';\n\nconst credentials: Credentials = {\n  token: process.env.CROWDIN_PERSONAL_TOKEN!,\n  organization: process.env.CROWDIN_ORGANIZATION, // Crowdin Enterprise only\n};\n\nconst client = new Client(credentials);\n```\n\n### Response Envelope Handling\n\n```ts\nconst listResponse = await client.tasksApi.withFetchAll().listTasks(projectId, options);\nconst tasks = listResponse.data.map((entry) => entry.data); // ResponseList<T>\n\nconst createResponse = await client.tasksApi.addTask(projectId, request);\nconst task = createResponse.data; // ResponseObject<T>\n```\n\n### Typed Request Models\n\n```ts\nconst request: TasksModel.CreateTaskRequest = {\n  title: 'My Task',\n  languageId: 'de',\n  type: 0,\n  fileIds: [12],\n};\n```\n\n### Error Handling\n\n```ts\nimport { CrowdinError, CrowdinValidationError } from '@crowdin/crowdin-api-client';\n\ntry {\n  // API call\n} catch (error) {\n  if (error instanceof CrowdinValidationError) throw error;\n  if (error instanceof CrowdinError) throw error;\n  throw error;\n}\n```\n\n## Common Mistakes\n\n| Mistake | Fix |\n|---------|-----|\n| Guessing endpoint methods from memory | Validate in local `index.d.ts` first |\n| Treating list response as object response | Check `ResponseList<T>` vs `ResponseObject<T>` and map accordingly |\n| Weakening or bypassing model typing | Use client `*Model` types in service signatures and fixtures |\n| Manual pagination loops by default | Prefer `.withFetchAll()` unless custom batching is required |\n| Uploading file directly to `createFile` | Create storage first, then pass `storageId` |\n| Catching all errors as generic | Branch `CrowdinValidationError` and `CrowdinError` explicitly |\n| Polling a status endpoint in a tight loop, or only until `finished` | Sleep between checks and treat `failed` and `canceled` as terminal — see [recipes](references/recipes.md) |\n| Composing a multi-step flow from memory | Start from the matching recipe in [references/recipes.md](references/recipes.md) |\n\n## Verification Gate\n\nAfter changing API-client usage:\n\n1. Run lint/type checks in the current project.\n2. Run at least one targeted test for the modified API flow.\n3. If tests fail on strict typing, fix fixture/model typing instead of loosening production types.\n\n## Review Checklist\n\n- Correct API module and method for the task.\n- Request models are explicit and include required fields.\n- Response mapping matches envelope shape.\n- Type safety is preserved without bypassing model contracts.\n- Pagination strategy matches expected volume.\n- Retry/timeout/runtime options fit environment.\n- Error handling distinguishes validation from generic API errors.\n\nReference docs: [Crowdin API Client modules](https://crowdin.github.io/crowdin-api-client-js/modules.html) · [API recipes](references/recipes.md)\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}