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

# Make your first app request

> Create a Salesforce environment, read its limits, and delete the environment with the TypeScript SDK.

We create a Salesforce environment, read its REST limits, and delete it. The `finally` block deletes the environment even if startup or the request fails.

## Install the SDK

Install `@usestatemachines/sdk` 0.6.0 or later. The SDK runs on Node.js 20.20 or later and is ESM only.

```sh theme={null}
npm install @usestatemachines/sdk
```

If your project uses version 0.5 or earlier, follow [Upgrade from SDK 0.5 to 0.6](/sdk-api/upgrading) first. Those versions call routes that the API no longer serves.

## Set your API key

In the [dashboard](https://app.usestatemachines.com), select the workspace for the environment. Open **API keys**, create a key, and save its value when it appears. If you cannot create a key, see [workspace access](/environments/access).

Set `STATEMACHINES_API_KEY` in the process that runs your script. Use your terminal's secret handling or your CI secret store. The SDK reads the process environment. It does not load `.env` files.

Check that the variable exists without printing it:

```sh theme={null}
test -n "$STATEMACHINES_API_KEY"
```

## Run the request

The example creates the environment with `wait: false`, so it gets the environment ID before startup finishes. It then waits for `running` inside `try`. `connect('salesforce')` returns credentials for the default actor, the Salesforce administrator.

```ts theme={null}
import { StateMachines } from '@usestatemachines/sdk';

const sm = new StateMachines();
const env = await sm.environments.create(
  { apps: ['salesforce'] },
  { wait: false },
);

try {
  const running = await sm.environments.wait(env.id, { status: 'running' });
  const salesforce = await running.connect('salesforce');
  const response = await salesforce.fetch('/services/data/v67.0/limits');

  if (!response.ok) {
    throw new Error(`Salesforce returned ${response.status}`);
  }

  console.log(response.status, await response.json());
} finally {
  await env.delete();
}
```

Save the example as `first-request.mts` and run it:

```sh theme={null}
npx tsx first-request.mts
```

A successful run prints HTTP `200` and the Salesforce limits response. A response other than success throws an error, so the run does not pass by mistake.

If startup fails or the wait times out, the `finally` block still deletes the environment. [Pause, resume, and delete environments](/environments/lifecycle) covers the other cases.

## Continue with your integration

Replace the limits request with a supported Salesforce request. Check `response.ok` before you treat a response as a success. The app returns its errors as HTTP responses. The SDK throws management API errors instead.

Use [named apps](/environments/create) when your test needs more than one Salesforce copy. Use [snapshots](/snapshots/reuse) when each test needs the same starting records. For failures before the first request, follow [startup troubleshooting](/troubleshooting/startup).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.