Background jobs
Use crowdinApp.cron.schedule(expression, task) to schedule background work. For work across installed accounts, forEachCrowdinConnection supplies an authenticated Crowdin API client for each stored installation, renews tokens automatically, and isolates installation failures.
Schedule a job
Section titled “Schedule a job”import { addCrowdinEndpoints, express } from '@crowdin/app-project-module';
const app = express();const crowdinApp = addCrowdinEndpoints(app, { name: 'Project cache', identifier: 'project-cache', description: 'Refresh project metadata hourly', clientId: process.env.CLIENT_ID!, clientSecret: process.env.CLIENT_SECRET!,});
crowdinApp.cron.schedule('0 * * * *', async () => { const result = await crowdinApp.forEachCrowdinConnection(async ({ client, credentials }) => { const projects = await client.projectsGroupsApi.withFetchAll().listProjects(); await crowdinApp.saveMetadata({ id: 'project-cache', crowdinId: credentials.id, metadata: JSON.stringify(projects.data.map(({ data }) => data)), }); }); console.log(`Updated ${result.processed}/${result.total} installations; ${result.failed.length} failed`);});
app.listen(3000);The scheduler defaults to Node.js cron. For serverless hosting, provide a custom Cron implementation and invoke it from the hosting platform’s scheduled handler; see Cloudflare Workers deployment. The helper itself does not schedule work and can also be awaited from an admin route or webhook handler.
Options and result
Section titled “Options and result”| Option | Default | Behavior |
|---|---|---|
concurrency | CRON_ORG_CONCURRENCY, or 5 | Positive safe integer; installations run in batches of at most this size. |
checkSubscription | true | Skip installations whose subscription is expired. Set to false for work that must also run for expired subscriptions, such as cleanup. |
The callback receives { client, credentials }. credentials is the original storage snapshot identifying the installation, not a source of current API tokens. Use client for API calls. The callback runs once per stored installation; enumerate projects inside it when needed.
The result contains total, processed, skippedExpired, and failed ({ crowdinId, error }[]). processed counts successfully completed callbacks; each installation has exactly one outcome. Client preparation and callback errors are logged and collected without aborting other installations. Empty storage returns zero counts and an empty failed array.
Invalid explicit concurrency rejects with RangeError; a storage listing failure rejects the whole run. Unauthorized configuration throws immediately. Subscription checks retain the SDK’s existing behavior: handled subscription-service HTTP errors allow processing to continue.
Authentication and execution limits
Section titled “Authentication and execution limits”Background token preparation uses the existing crowdin_app, authorization_code, and crowdin_agent flows. crowdin_app_with_code requires a code from a request JWT and is not supported for background iteration: each stored installation is reported in failed, and its callback is not called.
Concurrency applies to one invocation only. Separate invocations or app replicas can overlap; this helper adds no retries or distributed locking. Design callbacks to tolerate repeated execution where needed. Avoid logging whole credentials or result errors without the application’s normal error sanitization.