> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pre.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Node.js SDK

> Generate and retrieve specifications with the published predev-api TypeScript client.

```bash theme={null}
npm install predev-api
```

The package is ESM and supports Node.js 18+.

## Generate and wait for a specification

```typescript theme={null}
import { PredevAPI } from 'predev-api';

const client = new PredevAPI({ apiKey: process.env.PREDEV_API_KEY! });
const job = await client.fastSpecAsync({
  input: 'Build a team task manager with projects and assignees.',
  currentContext: 'Use TypeScript and preserve organization-scoped access.',
});
console.log('Save this ID:', job.specId);
const deadline = Date.now() + 600_000;

async function waitForSpec() {
  while (Date.now() < deadline) {
    const spec = await client.getSpecStatus(job.specId);
    if (spec.status === 'completed') return spec;
    if (spec.status === 'failed') {
      throw new Error(spec.errorMessage ?? 'Specification failed');
    }
    await new Promise(resolve => setTimeout(resolve, 5_000));
  }
  throw new Error('Polling deadline reached; retrieve the saved spec ID later.');
}

const spec = await waitForSpec();
console.log(spec.codingAgentSpecMarkdown);
```

## Method reference

| Method                   | Parameters                                            | Return                            |
| ------------------------ | ----------------------------------------------------- | --------------------------------- |
| `fastSpec(options)`      | `input`, optional `currentContext`, `docURLs`, `file` | `Promise<SpecResponse>`           |
| `deepSpec(options)`      | Same                                                  | `Promise<SpecResponse>`           |
| `fastSpecAsync(options)` | Same                                                  | `Promise<AsyncResponse>`          |
| `deepSpecAsync(options)` | Same                                                  | `Promise<AsyncResponse>`          |
| `getSpecStatus(specId)`  | Specification ID                                      | `Promise<SpecResponse>`           |
| `listSpecs(params)`      | Optional `limit`, `skip`, `endpoint`, `status`        | `Promise<ListSpecsResponse>`      |
| `findSpecs(params)`      | Required `query`; same filters                        | `Promise<ListSpecsResponse>`      |
| `getCreditsBalance()`    | None                                                  | `Promise<CreditsBalanceResponse>` |

All methods use `https://api.pre.dev` by default. The constructor accepts `apiKey` and optional `baseUrl`; it has no timeout, retry, or custom-header option. Use direct HTTP when you need those controls. A polling deadline does not abort an in-flight SDK request.

## History and credits

```typescript theme={null}
const page = await client.findSpecs({ query: 'report|export', status: 'completed' });
for (const summary of page.specs) {
  console.log(summary._id, summary.input);
}
const balance = await client.getCreditsBalance();
console.log(balance.creditsRemaining);
```

List and search return summaries. Retrieve a specific ID for full bodies and graphs. Optional artifacts can be absent or null; see [inputs and outputs](/architect-agent/inputs-and-outputs).

## File uploads

Pass a **Blob with an accepted MIME type**. SDK 1.1.0 encodes its `{ data: Buffer, name }` alternative as `application/octet-stream`, which the API's file filter does not accept.

```typescript theme={null}
import { readFile } from 'node:fs/promises';

const bytes = await readFile('requirements.pdf');
const upload = await client.fastSpecAsync({
  input: 'Create an implementation plan from these requirements.',
  file: new Blob([new Uint8Array(bytes)], { type: 'application/pdf' }),
  docURLs: ['https://www.postgresql.org/docs/current/'],
});
console.log(upload.specId);
```

The SDK serializes `docURLs` correctly for multipart requests. It generates a filename for Blob uploads; use direct multipart HTTP if preserving the original filename matters. See [accepted formats and limits](/architect-agent/inputs-and-outputs#upload-a-file).

## Errors

```typescript theme={null}
import { AuthenticationError, RateLimitError, PredevAPIError } from 'predev-api';

try {
  await client.listSpecs({ limit: 20 });
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Check the API key and account access at pre.dev/projects/key.');
  } else if (error instanceof RateLimitError) {
    console.error('Back off before retrying.');
  } else if (error instanceof PredevAPIError) {
    console.error(error.message);
  } else {
    throw error;
  }
}
```

The base exception has no `statusCode` property. Browser gate errors have additional typed subclasses; see [errors and retries](/api-reference/errors). An Architect `402` without a machine-readable browser gate code raises `PredevAPIError`.

Continue with the [Browser Agents Node guide](/browser-agents/sdks/node), [npm package](https://www.npmjs.com/package/predev-api), or [SDK source](https://github.com/predotdev/predev-api).
