---
updatedAt: 2026-05-19T03:29:06.000Z
---

Fetch the complete documentation index at: https://docs.usestable.com/llms.txt. Use this file to discover all available pages before exploring further. Append .md to any documentation page URL to get its markdown version.

# Create a Registered Agent Location

Learn how to add a new **registered agent** `Location` to your existing `Organization` so a company can receive service of process and state correspondence in a given jurisdiction.

> 📘 This guide covers **registered agent** locations only. To create a **CMRA** location (a physical mailbox for general mail reception), see [Create and Onboard a New CMRA Location](https://docs.usestable.com/docs/create-and-onboard-a-new-location) instead.

# Overview

A registered agent location is the address at which Stable, acting as registered agent, accepts service of process and official state mail on behalf of one of your companies in a single US jurisdiction. Unlike a CMRA, a registered agent location:

* Is tied to an existing `Company` (you must create the company first)
* Does **not** require USPS Form 1583, document uploads, or a signature packet
* Is requested with a 2-letter US state code (for example `WY` or `DE`) rather than an IATA-style facility code
* May briefly return with `status: "pending"` while we finish provisioning the address with our partners

You'll learn how to:

* Create a `Company` (if you don't have one yet)
* Create a registered agent `Location` for that company in a given jurisdiction
* Provide jurisdiction-specific extra information (e.g. for Wyoming)
* Handle a `pending` response and detect when the location becomes `active`

# Prerequisites

Before you begin, you'll need:

* [A Stable API key](https://docs.usestable.com/reference/authentication)
* A registered agent jurisdiction code (a 2-letter US state or territory code, e.g. `WY`, `DE`, `CA`). See [Location codes](https://docs.usestable.com/docs/location-codes) for the full list
* The `id` of an existing `Company`. If you don't have one yet, you'll create it as Step 1 below

# Authentication

All API requests require authentication using your API key in the `x-api-key` header:

```bash cURL
curl -H "x-api-key: your-api-key" https://api.usestable.com/v1/...
```

```javascript JavaScript
const fetch = require('node-fetch');

const url = 'https://api.usestable.com/v1/locations';
const options = {
  headers: {
    'x-api-key': 'your-api-key',
    'Content-Type': 'application/json',
  },
  // ...
};

fetch(url, options)
  .then(response => console.log('Response:', response.json()))
  .catch(error => console.error('Error:', error));
```

```python Python
import requests

url = 'https://api.usestable.com/v1/...'
headers = {
    'x-api-key': 'your-api-key',
    'Content-Type': 'application/json',
}

response = requests.get(url, headers=headers)

if response.ok:
    print(response.json())
else:
    print(f"Error: {response.status_code}, {response.text}")
```

<Callout icon="🔒" theme="default">
  ### **API Key Security**

  Keep your API key secure and never expose it in client-side code. All API requests should be made from your backend services.
</Callout>

# Process Overview

The registered agent `Location` creation flow follows these steps:

1. Create a `Company` (or reuse an existing one)
2. Create the registered agent `Location` in a given jurisdiction
3. Handle the response, including the possible `pending` status

There is no document upload step and no signature packet. Most registered agent locations are returned in `active` status on the first request.

## Step 1: Create a Company

A registered agent location must be attached to a `Company`. If you've already created the company, skip to Step 2 and use its `id`.

```bash cURL
curl -X POST https://api.usestable.com/v1/companies \
  -H "x-api-key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "legalName": "Ada'\''s Apples LLC",
    "entityType": "limited-liability-company",
    "jurisdictions": ["WY"],
    "formationJurisdiction": "WY",
    "formationDate": "2024-01-15"
  }'
```

```javascript JavaScript
const fetch = require('node-fetch');

const url = 'https://api.usestable.com/v1/companies';

const body = {
  legalName: "Ada's Apples LLC",
  entityType: 'limited-liability-company',
  jurisdictions: ['WY'],
  formationJurisdiction: 'WY',
  formationDate: '2024-01-15',
};

const options = {
  method: 'POST',
  headers: {
    'x-api-key': 'your-api-key',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(body),
};

fetch(url, options)
  .then(response => response.json())
  .then(data => console.log('Response:', data))
  .catch(error => console.error('Error:', error));
```

```python Python
import requests

url = 'https://api.usestable.com/v1/companies'

body = {
    "legalName": "Ada's Apples LLC",
    "entityType": "limited-liability-company",
    "jurisdictions": ["WY"],
    "formationJurisdiction": "WY",
    "formationDate": "2024-01-15",
}

headers = {
    "x-api-key": "your-api-key",
    "Content-Type": "application/json",
}

response = requests.post(url, headers=headers, json=body)

if response.ok:
    print("Response:", response.json())
else:
    print(f"Error: {response.status_code}, {response.text}")
```

Save the `id` returned in the response. You'll pass it as `companyId` in Step 2.

## Step 2: Create the Registered Agent Location

Send a `POST /v1/locations` with the jurisdiction's 2-letter state code as `locationCode` and the company's `id` as `companyId`.

```bash cURL
curl -X POST https://api.usestable.com/v1/locations \
  -H "x-api-key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "locationCode": "DE",
    "companyId": "550e8400-e29b-41d4-a716-446655440000"
  }'
```

```javascript JavaScript
const fetch = require('node-fetch');

const url = 'https://api.usestable.com/v1/locations';

const body = {
  locationCode: 'DE',
  companyId: '550e8400-e29b-41d4-a716-446655440000',
};

const options = {
  method: 'POST',
  headers: {
    'x-api-key': 'your-api-key',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(body),
};

fetch(url, options)
  .then(response => response.json())
  .then(data => console.log('Response:', data))
  .catch(error => console.error('Error:', error));
```

```python Python
import requests

url = 'https://api.usestable.com/v1/locations'

body = {
    "locationCode": "DE",
    "companyId": "550e8400-e29b-41d4-a716-446655440000",
}

headers = {
    "x-api-key": "your-api-key",
    "Content-Type": "application/json",
}

response = requests.post(url, headers=headers, json=body)

if response.ok:
    print("Response:", response.json())
else:
    print(f"Error: {response.status_code}, {response.text}")
```

### Field Reference

* **`locationCode`** (required): 2-letter US state or territory code such as `DE`, `WY`, `CA`. See [Location codes](https://docs.usestable.com/docs/location-codes) for the full list of registered agent jurisdictions. Do **not** pass an IATA-style CMRA code (e.g. `SFO1`) here, it will be routed through the CMRA flow.
* **`companyId`** (required): UUID of an existing `Company`. The location will be created as that company's registered agent in the chosen jurisdiction.
* **`autoScan`** (optional): For registered agent locations, only `true` is permitted. The field defaults to `true`, so you can omit it.
* **`additionalInformation`** (required for some jurisdictions, e.g. Wyoming): Jurisdiction-specific extra data. See [Jurisdiction-Specific Requirements](#jurisdiction-specific-requirements) below.
* **`metadata`** (optional): Arbitrary key/value pairs to attach to the location. Each value must be a string or number.

> 📘 **Fields that are not allowed**
>
> `platformPrefill` is for CMRA onboarding only and will be rejected for registered agent locations.

### Response (active)

In most cases, the request returns with `status: "active"` once provisioning completes. The `address` fields will be populated with the registered agent address assigned to your company in that jurisdiction:

```json JSON
{
  "id": "70a3d702-bf1d-4153-8eb2-d3d889aff7f0",
  "status": "active",
  "address": {
    "line1": "<assigned registered agent street>",
    "line2": "",
    "city": "<city>",
    "state": "DE",
    "postalCode": "<postal code>"
  },
  "type": "registeredAgent",
  "onboarding": {
    "status": "complete"
  },
  "metadata": null
}
```

### Response (pending)

If provisioning takes longer than the request window allows, the response will return with `status: "pending"`. The `address` is still populated in this case, with the same fields as the active response:

```json JSON
{
  "id": "70a3d702-bf1d-4153-8eb2-d3d889aff7f0",
  "status": "pending",
  "address": {
    "line1": "<assigned registered agent street>",
    "line2": "",
    "city": "<city>",
    "state": "DE",
    "postalCode": "<postal code>"
  },
  "type": "registeredAgent",
  "onboarding": {
    "status": "complete"
  },
  "metadata": null
}
```

A `pending` response means the location has been accepted and is being provisioned with our partners. Once provisioning completes, the location will transition to `active`. Keep the `id` from the response and poll the GET endpoint to detect the transition.

## Step 3: Handling a Pending Location

When a location is returned as `pending`, do not retry the create request. The first create call has already succeeded and provisioning is underway; a second create call for the same company and jurisdiction will be rejected with an error (see [Registered agent already exists](#registered-agent-already-exists) below). Instead, save the `id` from the create response and poll for status updates.

### Polling for Activation

Call `GET /v1/locations/{id}` on an interval until `status` becomes `active`. We recommend exponential backoff starting at around 1 second and capping at around 30 seconds between polls.

```bash cURL
curl https://api.usestable.com/v1/locations/70a3d702-bf1d-4153-8eb2-d3d889aff7f0 \
  -H "x-api-key: your-api-key"
```

```javascript JavaScript
async function waitForActive(locationId, apiKey, { maxAttempts = 20 } = {}) {
  let delay = 1000;
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const res = await fetch(
      `https://api.usestable.com/v1/locations/${locationId}`,
      { headers: { 'x-api-key': apiKey } },
    );
    const location = await res.json();
    if (location.status === 'active') {
      return location;
    }
    await new Promise((r) => setTimeout(r, delay));
    delay = Math.min(delay * 2, 30000);
  }
  throw new Error('Location did not become active in time');
}
```

```python Python
import time
import requests

def wait_for_active(location_id, api_key, max_attempts=20):
    delay = 1
    for _ in range(max_attempts):
        res = requests.get(
            f"https://api.usestable.com/v1/locations/{location_id}",
            headers={"x-api-key": api_key},
        )
        location = res.json()
        if location["status"] == "active":
            return location
        time.sleep(delay)
        delay = min(delay * 2, 30)
    raise TimeoutError("Location did not become active in time")
```

### Response Once Active

```json JSON
{
  "id": "70a3d702-bf1d-4153-8eb2-d3d889aff7f0",
  "status": "active",
  "address": {
    "line1": "<assigned registered agent street>",
    "line2": "",
    "city": "<city>",
    "state": "DE",
    "postalCode": "<postal code>"
  },
  "type": "registeredAgent",
  "onboarding": {
    "status": "complete"
  },
  "metadata": null
}
```

> 📘 **Do not retry the create request**
>
> A `pending` status is not a failure. The create call succeeded and provisioning is underway. Retrying the `POST /v1/locations` call for the same company and jurisdiction will be rejected with a `409 Conflict` ([Registered agent already exists](#registered-agent-already-exists)). Always poll the existing `id` instead.

## Jurisdiction-Specific Requirements

Some jurisdictions require additional information on the company before a registered agent location can be activated. Pass these through `additionalInformation` on the create request.

### Wyoming (`WY`)

Wyoming requires `additionalInformation` to be provided on registered agent creation. Pass the company's management structure and the officials responsible for the entity:

```json JSON
{
  "locationCode": "WY",
  "companyId": "550e8400-e29b-41d4-a716-446655440000",
  "additionalInformation": {
    "managementType": "Member Managed",
    "officialMember": {
      "firstName": "Ada",
      "lastName": "Lovelace"
    }
  }
}
```

Supported fields on `additionalInformation`:

* `managementType` (string, e.g. `"Member Managed"` or `"Manager Managed"`)
* `official`, `officialDirector`, `officialManager`, `officialMember`, `officialPartner`, `officialPresident`, `officialSecretary`, `officialTreasurer`: each takes `{ firstName, lastName }`

Provide the official fields that match the company's entity type and management structure.

### Other Jurisdictions

Most jurisdictions do not require `additionalInformation`. Pass only `locationCode` and `companyId`. If we add new jurisdiction-specific requirements, this section will be updated.

# Error Handling

### Registered agent already exists

```json JSON
{
  "status": 409,
  "message": "A registered agent already exists for Ada's Apples LLC in DE."
}
```

You'll get this when you call `POST /v1/locations` for a company and jurisdiction that already has a registered agent location, including the case where the first call returned `status: "pending"` and is still provisioning. Don't retry the create call; instead, look up the existing location by ID (or by listing the company's locations) and poll its status until it becomes `active`.

### Missing `companyId`

```json JSON
{
  "status": 400,
  "message": "companyId is required for registered agent locations"
}
```

Solution: Include `companyId` in your request body.

### `platformPrefill` Not Allowed

```json JSON
{
  "status": 400,
  "message": "platformPrefill is not allowed for registered agent locations"
}
```

Solution: Remove `platformPrefill` from your request body. It is only used for CMRA locations.

### `autoScan: false` Not Allowed

```json JSON
{
  "status": 400,
  "message": "autoScan cannot be false for registered agent locations"
}
```

Solution: Omit `autoScan` or set it to `true`. Registered agent mail is always scanned.

### Missing `additionalInformation` for Wyoming

```json JSON
{
  "status": 400,
  "message": "additionalInformation is required for WY"
}
```

Solution: Include the required `additionalInformation` object on the create request. See [Wyoming](#wyoming-wy) above.

### Invalid Location Code

```json JSON
{
  "status": 400,
  "message": "Validation error(s) when parsing body: 'locationCode must be a CMRA code (...) or a registered agent jurisdiction code (AK, AL, ...). See https://docs.usestable.com/docs/location-codes for more information.'"
}
```

Solution: Use one of the supported 2-letter jurisdiction codes from the [Location codes](https://docs.usestable.com/docs/location-codes) page.

# Best Practices

* **Always store the `id` from a `pending` response** before polling. Treat the create call as a single-use action: a second create for the same company and jurisdiction returns `409 Conflict`.
* **Use exponential backoff** when polling for `active` status. Most pending locations activate in well under a minute.
* **Validate Wyoming inputs** on your side before submitting, so you can surface clear errors to your users about which officials are needed.
* **Surface a clear loading state** to your end user while a registered agent location is `pending`, with messaging that the address is being provisioned.