# Async operations

Some Conversation Orchestrator operations run asynchronously. They return `202 Accepted` immediately and complete in the background. This page explains which operations are async, how to poll for completion, and how to extract the resulting resource ID.

## Which operations are async?

| Async methods                                                                                                                                                                                                              | Endpoint                          |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- |
| [`POST`](/docs/api/conversations/v2/Configuration#create-configuration), [`PUT`](/docs/api/conversations/v2/Configuration#update-configuration), [`DELETE`](/docs/api/conversations/v2/Configuration#delete-configuration) | `/v2/ControlPlane/Configurations` |
| [`DELETE`](/docs/api/conversations/v2/Conversation#delete-conversation-async)                                                                                                                                              | `/v2/Conversations/{Sid}`         |
| [`POST`](/docs/api/memory/v1/Store#create-store), [`DELETE`](/docs/api/memory/v1/Store#delete-store)                                                                                                                       | `/v1/ControlPlane/Stores`         |

All other operations run synchronously and return their results immediately.

## Poll for completion

The initial `202 Accepted` response contains a `statusUrl` in the body and a `Retry-After` header. Send `GET` requests to the `statusUrl` until `status` is `COMPLETED` or `FAILED`.

Poll for operation completion

```js
// Download the helper library from https://www.twilio.com/docs/node/install
const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";

// Find your Account SID at twilio.com/console
// Provision API Keys at twilio.com/console/runtime/api-keys
// and set the environment variables. See http://twil.io/secure
// For local testing, you can use your Account SID and Auth token
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const apiKey = process.env.TWILIO_API_KEY;
const apiSecret = process.env.TWILIO_API_SECRET;
const client = twilio(apiKey, apiSecret, { accountSid: accountSid });

async function fetchOperationStatus() {
  const operation = await client.conversations.v2
    .operations("OPERATION_ID")
    .fetch();

  console.log(operation.operationId);
}

fetchOperationStatus();
```

```python
# Download the helper library from https://www.twilio.com/docs/python/install
import os
from twilio.rest import Client

# Find your Account SID at twilio.com/console
# Provision API Keys at twilio.com/console/runtime/api-keys
# and set the environment variables. See http://twil.io/secure
# For local testing, you can use your Account SID and Auth token
api_key = os.environ["TWILIO_API_KEY"]
api_secret = os.environ["TWILIO_API_SECRET"]
account_sid = os.environ["TWILIO_ACCOUNT_SID"]
client = Client(api_key, api_secret, account_sid)

operation = client.conversations.v2.operations("OPERATION_ID").fetch()

print(operation.operation_id)
```

```csharp
// Install the C# / .NET helper library from twilio.com/docs/csharp/install

using System;
using Twilio;
using Twilio.Rest.Conversations.V2;
using System.Threading.Tasks;

class Program {
    public static async Task Main(string[] args) {
        // Find your Account SID at twilio.com/console
        // Provision API Keys at twilio.com/console/runtime/api-keys
        // and set the environment variables. See http://twil.io/secure
        // For local testing, you can use your Account SID and Auth token
        string apiKey = Environment.GetEnvironmentVariable("TWILIO_API_KEY");
        string apiSecret = Environment.GetEnvironmentVariable("TWILIO_API_SECRET");
        string accountSid = Environment.GetEnvironmentVariable("TWILIO_ACCOUNT_SID");

        TwilioClient.Init(apiKey, apiSecret, accountSid);

        var operation = await OperationResource.FetchAsync(pathSid: "OPERATION_ID");

        Console.WriteLine(operation.OperationId);
    }
}
```

```java
// Install the Java helper library from twilio.com/docs/java/install

import com.twilio.Twilio;
import com.twilio.rest.conversations.v2.Operation;

public class Example {
    // Find your Account SID at twilio.com/console
    // Provision API Keys at twilio.com/console/runtime/api-keys
    // and set the environment variables. See http://twil.io/secure
    // For local testing, you can use your Account SID and Auth token
    public static final String API_KEY = System.getenv("TWILIO_API_KEY");
    public static final String API_SECRET = System.getenv("TWILIO_API_SECRET");
    public static final String ACCOUNT_SID = System.getenv("TWILIO_ACCOUNT_SID");

    public static void main(String[] args) {
        Twilio.init(API_KEY, API_SECRET, ACCOUNT_SID);
        Operation.FetchOperationResponse response = Operation.fetcher("OPERATION_ID").fetch();

        System.out.println(response.getOperationId());
    }
}
```

```ruby
# Download the helper library from https://www.twilio.com/docs/ruby/install
require 'twilio-ruby'

# Find your Account SID at twilio.com/console
# Provision API Keys at twilio.com/console/runtime/api-keys
# and set the environment variables. See http://twil.io/secure
# For local testing, you can use your Account SID and Auth token
api_key = ENV['TWILIO_API_KEY']
api_secret = ENV['TWILIO_API_SECRET']
account_sid = ENV['TWILIO_ACCOUNT_SID']
@client = Twilio::REST::Client.new(api_key, api_secret, account_sid)

operation = @client
            .conversations
            .v2
            .operations('OPERATION_ID')
            .fetch

puts operation.operation_id
```

```bash
curl -X GET "https://conversations.twilio.com/v2/ControlPlane/Operations/OPERATION_ID" \
-u $TWILIO_API_KEY:$TWILIO_API_SECRET
```

Replace *OPERATION\_ID* with the operation ID from the `statusUrl`.

A completed memory store operation returns the created resource in `result.id`:

```json
{
  "operationId": "proc_job_01kpttrkrnfjgvwjwcwggqdk96",
  "status": "COMPLETED",
  "result": {
    "id": "mem_store_01kpttrksqe08rhv122gzq52ax",
    "type": "RESOURCE_ID"
  }
}
```

| Status      | Meaning                | What to do                                          |
| ----------- | ---------------------- | --------------------------------------------------- |
| `PENDING`   | Queued or running.     | Keep polling.                                       |
| `COMPLETED` | Finished successfully. | Read `result.id` (or see the following limitation). |
| `FAILED`    | The operation failed.  | Inspect the `error` field for details.              |

If `status` stays `PENDING` for more than a few minutes, contact [Twilio Support](https://support.twilio.com) with the `operationId`.

## Known limitation: configuration operations don't return a resource ID

Configuration `POST` and `PUT` operations complete with `status: COMPLETED` but don't populate `result.id`. To find the configuration ID, list configurations and filter by `displayName`:

```js
// Download the helper library from https://www.twilio.com/docs/node/install
const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";

// Find your Account SID at twilio.com/console
// Provision API Keys at twilio.com/console/runtime/api-keys
// and set the environment variables. See http://twil.io/secure
// For local testing, you can use your Account SID and Auth token
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const apiKey = process.env.TWILIO_API_KEY;
const apiSecret = process.env.TWILIO_API_SECRET;
const client = twilio(apiKey, apiSecret, { accountSid: accountSid });

async function listConfiguration() {
  const configurations = await client.conversations.v2.configurations.list({
    limit: 20,
  });

  configurations.forEach((c) => console.log(c.id));
}

listConfiguration();
```

```python
# Download the helper library from https://www.twilio.com/docs/python/install
import os
from twilio.rest import Client

# Find your Account SID at twilio.com/console
# Provision API Keys at twilio.com/console/runtime/api-keys
# and set the environment variables. See http://twil.io/secure
# For local testing, you can use your Account SID and Auth token
api_key = os.environ["TWILIO_API_KEY"]
api_secret = os.environ["TWILIO_API_SECRET"]
account_sid = os.environ["TWILIO_ACCOUNT_SID"]
client = Client(api_key, api_secret, account_sid)

configurations = client.conversations.v2.configurations.list(limit=20)

for record in configurations:
    print(record.id)
```

```csharp
// Install the C# / .NET helper library from twilio.com/docs/csharp/install

using System;
using Twilio;
using Twilio.Rest.Conversations.V2;
using System.Threading.Tasks;

class Program {
    public static async Task Main(string[] args) {
        // Find your Account SID at twilio.com/console
        // Provision API Keys at twilio.com/console/runtime/api-keys
        // and set the environment variables. See http://twil.io/secure
        // For local testing, you can use your Account SID and Auth token
        string apiKey = Environment.GetEnvironmentVariable("TWILIO_API_KEY");
        string apiSecret = Environment.GetEnvironmentVariable("TWILIO_API_SECRET");
        string accountSid = Environment.GetEnvironmentVariable("TWILIO_ACCOUNT_SID");

        TwilioClient.Init(apiKey, apiSecret, accountSid);

        var configurations = await ConfigurationResource.ReadAsync(limit: 20);

        foreach (var record in configurations) {
            Console.WriteLine(record.Id);
        }
    }
}
```

```java
// Install the Java helper library from twilio.com/docs/java/install

import com.twilio.Twilio;
import com.twilio.rest.conversations.v2.Configuration;
import com.twilio.base.ResourceSet;

public class Example {
    // Find your Account SID at twilio.com/console
    // Provision API Keys at twilio.com/console/runtime/api-keys
    // and set the environment variables. See http://twil.io/secure
    // For local testing, you can use your Account SID and Auth token
    public static final String API_KEY = System.getenv("TWILIO_API_KEY");
    public static final String API_SECRET = System.getenv("TWILIO_API_SECRET");
    public static final String ACCOUNT_SID = System.getenv("TWILIO_ACCOUNT_SID");

    public static void main(String[] args) {
        Twilio.init(API_KEY, API_SECRET, ACCOUNT_SID);
        ResourceSet<Configuration.ListConfigurationResponse> configurations = Configuration.reader().limit(20).read();

        for (Configuration.ListConfigurationResponse configuration : configurations) {
            System.out.println(configuration.getId());
        }
    }
}
```

```ruby
# Download the helper library from https://www.twilio.com/docs/ruby/install
require 'twilio-ruby'

# Find your Account SID at twilio.com/console
# Provision API Keys at twilio.com/console/runtime/api-keys
# and set the environment variables. See http://twil.io/secure
# For local testing, you can use your Account SID and Auth token
api_key = ENV['TWILIO_API_KEY']
api_secret = ENV['TWILIO_API_SECRET']
account_sid = ENV['TWILIO_ACCOUNT_SID']
@client = Twilio::REST::Client.new(api_key, api_secret, account_sid)

configurations = @client
                 .conversations
                 .v2
                 .configurations
                 .list(limit: 20)

configurations.each do |record|
   puts record.id
end
```

```bash
curl -X GET "https://conversations.twilio.com/v2/ControlPlane/Configurations?PageSize=20" \
-u $TWILIO_API_KEY:$TWILIO_API_SECRET
```

Memory store operations populate `result.id` and don't need this workaround.

## Idempotency

Configuration operations accept an `Idempotency-Key` header so you can safely retry a request without creating a duplicate operation. The key is a UUID that you generate on the client. Generate a new UUID for each request, and reuse the same value only when you're retrying that specific request after a network failure or timeout. Within 24 hours, any retry with the same key returns the original `202` response instead of triggering another operation. Each idempotency key is scoped to your account and region.

## Next steps

* [Quickstart](/docs/conversations/orchestrator/quickstart): Create your first configuration.
* [Troubleshooting](/docs/conversations/orchestrator/troubleshooting): Resolve operation errors and stuck operations.
