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

# Quickstart

> Get started with the D3 Business API in minutes.

1. Generate an API key.
2. Upload a file (`initiate-upload` → presigned PUT → `complete-upload`).
3. Create an operation.
4. Poll for status.

## 1. Get an API key

API keys are managed through the D3 dashboard. To generate an API key:

1. **Sign in** to your account at [dragdropdo.com/auth/signin](https://dragdropdo.com/auth/signin)
2. Navigate to your **Account** section
3. Go to the **Generate API Key** section
4. Create a new API key with a descriptive name
5. Copy and securely store your API key – it is only shown once

Once you have your API key, you can use it to initialize the client:

<CodeGroup>
  ```ts NODE theme={null}
  import { Dragdropdo } from "dragdropdo-sdk";

  const client = new Dragdropdo({
  apiKey: "d3_live_xxx", // Your API key from the dashboard
  baseURL: "https://api.dragdropdo.com",
  });

  ```

  ```python PYTHON theme={null}
  from dragdropdo_sdk import Dragdropdo, D3ClientConfig

  client = Dragdropdo(
      api_key="d3_live_xxx",  # Your API key from the dashboard
      base_url="https://api.dragdropdo.com"
  )
  ```

  ```php PHP theme={null}
  use DragdropdoSdk\Dragdropdo;

  $client = new Dragdropdo([
      'api_key' => 'd3_live_xxx', // Your API key from the dashboard
      'base_url' => 'https://api.dragdropdo.com',
  ]);
  ```

  ```ruby RUBY theme={null}
  require 'dragdropdo_sdk'

  client = DragdropdoSdk::Dragdropdo.new(
    api_key: 'd3_live_xxx', # Your API key from the dashboard
    base_url: 'https://api.dragdropdo.com'
  )
  ```

  ```go GO theme={null}
  import "github.com/d3/dragdropdo-sdk-go"

  client, err := d3.NewDragdropdo(d3.Config{
      APIKey:  "d3_live_xxx", // Your API key from the dashboard
      BaseURL: "https://api.dragdropdo.com",
  })
  ```

  ```java JAVA theme={null}
  import com.dragdropdo.sdk.Dragdropdo;
  import com.dragdropdo.sdk.DragdropdoConfig;

  Dragdropdo client = new Dragdropdo(
      new DragdropdoConfig("d3_live_xxx") // Your API key from the dashboard
          .setBaseUrl("https://api.dragdropdo.com")
  );
  ```
</CodeGroup>

Store your `api_key` securely – it is only shown once in the dashboard. Authentication for `/api/v1` endpoints uses this raw key.

## 2. Upload a file

Uploads use presigned URLs. The flow is: **`POST /api/v1/initiate-upload`** (get `file_key`, `object_name`, `upload_id`, and presigned URLs) → **HTTP PUT** each file part to its URL (collect the **`ETag`** from each response) → **`POST /api/v1/complete-upload`** to finalize the multipart upload and register the file for operations. The complete-upload request body includes `file_key`, `object_name`, `upload_id`, and `parts` (each part’s `etag` and `part_number`); the JSON response includes `message` and `file_key`. See **[Upload → Complete upload](/business-api/upload#complete-upload)** for the full request and response schema, authentication, and ETag handling. Official SDKs perform all of these steps when you call `uploadFile` / `upload_file`.

<CodeGroup>
  ```bash cURL theme={null}
  # Step 1: Initiate upload
  curl -X POST https://api.dragdropdo.com/api/v1/initiate-upload \
    -H "Authorization: Bearer your-api-key" \
    -H "Content-Type: application/json" \
    -d '{
      "file_name": "document.pdf",
      "size": 1234567,
      "mime_type": "application/pdf",
      "parts": 1
    }'

  # Step 2: Upload to presigned URL (use ETag from response headers in step 3)

  curl -X PUT "https://minio/..." \
   -H "Content-Type: application/pdf" \
   --data-binary "@document.pdf"

  # Step 3: Complete upload — required to finalize the upload and obtain a usable file_key

  curl -X POST https://api.dragdropdo.com/api/v1/complete-upload \
    -H "Authorization: Bearer your-api-key" \
    -H "Content-Type: application/json" \
    -d '{
      "file_key": "file_key_123",
      "object_name": "external/...",
      "upload_id": "upload-id-from-initiate-response",
      "parts": [
        { "etag": "etag-from-put-response", "part_number": 1 }
      ]
    }'

  ```

  ```ts NODE theme={null}
  import { Dragdropdo } from "dragdropdo-sdk";

  const client = new Dragdropdo({
    apiKey: "your-api-key",
    baseURL: "https://api.dragdropdo.com",
  });

  // initiate-upload, presigned PUT(s), and POST /api/v1/complete-upload are handled automatically
  const uploadResult = await client.uploadFile({
    file: "/path/to/document.pdf",
    fileName: "document.pdf",
    mimeType: "application/pdf",
  });

  console.log("File key:", uploadResult.fileKey);
  // You can now use file_key in operations
  ```

  ```python PYTHON theme={null}
  from dragdropdo_sdk import Dragdropdo, D3ClientConfig

  client = Dragdropdo(
      api_key="your-api-key",
      base_url="https://api.dragdropdo.com"
  )

  # initiate-upload, presigned PUT(s), and POST /api/v1/complete-upload are handled automatically
  upload_result = client.upload_file(
      file="/path/to/document.pdf",
      file_name="document.pdf",
      mime_type="application/pdf"
  )

  print("File key:", upload_result.file_key)
  # You can now use file_key in operations
  ```

  ```php PHP theme={null}
  use DragdropdoSdk\Dragdropdo;

  $client = new Dragdropdo([
      'api_key' => 'your-api-key',
      'base_url' => 'https://api.dragdropdo.com',
  ]);

  // initiate-upload, presigned PUT(s), and POST /api/v1/complete-upload are handled automatically
  $uploadResult = $client->uploadFile([
      'file' => '/path/to/document.pdf',
      'file_name' => 'document.pdf',
      'mime_type' => 'application/pdf',
  ]);

  echo "File key: " . $uploadResult['file_key'] . "\n";
  // You can now use file_key in operations
  ```

  ```ruby RUBY theme={null}
  require 'dragdropdo_sdk'

  client = DragdropdoSdk::Dragdropdo.new(
    api_key: 'your-api-key',
    base_url: 'https://api.dragdropdo.com'
  )

  # initiate-upload, presigned PUT(s), and POST /api/v1/complete-upload are handled automatically
  upload_result = client.upload_file(
    file: '/path/to/document.pdf',
    file_name: 'document.pdf',
    mime_type: 'application/pdf'
  )

  puts "File key: #{upload_result[:file_key]}"
  # You can now use file_key in operations
  ```

  ```go GO theme={null}
  import "github.com/d3/dragdropdo-sdk-go"

  client, _ := d3.NewDragdropdo(d3.Config{
      APIKey:  "your-api-key",
      BaseURL: "https://api.dragdropdo.com",
  })

  // initiate-upload, presigned PUT(s), and POST /api/v1/complete-upload are handled automatically
  uploadResult, _ := client.UploadFile(d3.UploadFileOptions{
      File:     "/path/to/document.pdf",
      FileName: "document.pdf",
      MimeType: "application/pdf",
  })

  fmt.Printf("File key: %s\n", uploadResult.FileKey)
  // You can now use file_key in operations
  ```

  ```java JAVA theme={null}
  import com.dragdropdo.sdk.Dragdropdo;
  import com.dragdropdo.sdk.DragdropdoConfig;
  import com.dragdropdo.sdk.models.*;

  Dragdropdo client = new Dragdropdo(
      new DragdropdoConfig("your-api-key")
          .setBaseUrl("https://api.dragdropdo.com")
  );

  // initiate-upload, presigned PUT(s), and POST /api/v1/complete-upload are handled automatically
  UploadResponse uploadResult = client.uploadFile(
      new UploadFileOptions()
          .setFile("/path/to/document.pdf")
          .setFileName("document.pdf")
          .setMimeType("application/pdf")
  );

  System.out.println("File key: " + uploadResult.getFileKey());
  // You can now use file_key in operations
  ```
</CodeGroup>

## 3. Create an operation

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.dragdropdo.com/api/v1/do \
    -H "Authorization: Bearer your-api-key" \
    -H "Content-Type: application/json" \
    -d '{
      "action": "convert",
      "file_keys": ["file_key_123"],
      "parameters": {
        "convert_to": "png"
      },
      "notes": {
        "user_id": "user-123",
        "source": "api"
      }
    }'
  ```

  ```ts NODE theme={null}
  import { Dragdropdo } from "dragdropdo-sdk";

  const client = new Dragdropdo({
    apiKey: "your-api-key",
    baseURL: "https://api.dragdropdo.com",
  });

  // Create convert operation
  const operation = await client.convert(["file_key_123"], "png", {
    user_id: "user-123",
    source: "api",
  });

  console.log("Main task ID:", operation.mainTaskId);
  ```

  ```python PYTHON theme={null}
  from dragdropdo_sdk import Dragdropdo, D3ClientConfig

  client = Dragdropdo(
      api_key="your-api-key",
      base_url="https://api.dragdropdo.com"
  )

  # Create convert operation
  operation = client.convert(
      file_keys=["file_key_123"],
      convert_to="png",
      notes={"user_id": "user-123", "source": "api"}
  )

  print("Main task ID:", operation.main_task_id)
  ```

  ```php PHP theme={null}
  use DragdropdoSdk\Dragdropdo;

  $client = new Dragdropdo([
      'api_key' => 'your-api-key',
      'base_url' => 'https://api.dragdropdo.com',
  ]);

  // Create convert operation
  $operation = $client->convert(
      ['file_key_123'],
      'png',
      ['user_id' => 'user-123', 'source' => 'api']
  );

  echo "Main task ID: " . $operation['main_task_id'] . "\n";
  ```

  ```ruby RUBY theme={null}
  require 'dragdropdo_sdk'

  client = DragdropdoSdk::Dragdropdo.new(
    api_key: 'your-api-key',
    base_url: 'https://api.dragdropdo.com'
  )

  # Create convert operation
  operation = client.convert(
    file_keys: ['file_key_123'],
    convert_to: 'png',
    notes: { user_id: 'user-123', source: 'api' }
  )

  puts "Main task ID: #{operation[:main_task_id]}"
  ```

  ```go GO theme={null}
  import "github.com/d3/dragdropdo-sdk-go"

  client, _ := d3.NewDragdropdo(d3.Config{
      APIKey:  "your-api-key",
      BaseURL: "https://api.dragdropdo.com",
  })

  // Create convert operation
  operation, _ := client.Convert(
      []string{"file_key_123"},
      "png",
      map[string]string{"user_id": "user-123", "source": "api"},
  )

  fmt.Printf("Main task ID: %s\n", operation.MainTaskID)
  ```

  ```java JAVA theme={null}
  import com.dragdropdo.sdk.Dragdropdo;
  import com.dragdropdo.sdk.DragdropdoConfig;
  import java.util.*;

  Dragdropdo client = new Dragdropdo(
      new DragdropdoConfig("your-api-key")
          .setBaseUrl("https://api.dragdropdo.com")
  );

  // Create convert operation
  OperationResponse operation = client.convert(
      List.of("file_key_123"),
      "png",
      Map.of("user_id", "user-123", "source", "api")
  );

  System.out.println("Main task ID: " + operation.getMainTaskId());
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "main_task_id": "task_abc123"
}
```

## 4. Poll for status

<CodeGroup>
  ```bash cURL theme={null}
  # Single status check
  curl -X GET https://api.dragdropdo.com/api/v1/status/task_abc123 \
    -H "Authorization: Bearer your-api-key"

  # Poll in a loop (bash example)

  while true; do
  response=$(curl -s -X GET https://api.dragdropdo.com/api/v1/status/task_abc123 \
   -H "Authorization: Bearer your-api-key")

  status=$(echo $response | jq -r '.operation_status')
  echo "Status: $status"

  if [ "$status" = "completed" ] || [ "$status" = "failed" ]; then
  echo $response | jq '.'
  break
  fi

  sleep 2
  done

  ```

  ```ts NODE theme={null}
  import { Dragdropdo } from "dragdropdo-sdk";

  const client = new Dragdropdo({
    apiKey: "your-api-key",
    baseURL: "https://api.dragdropdo.com",
  });

  // Poll until completion
  const status = await client.pollStatus({
    mainTaskId: "task_abc123",
    interval: 2000, // Check every 2 seconds
    onUpdate: (status) => {
      console.log("Status:", status.operationStatus);
    },
  });

  if (status.operationStatus === "completed") {
    status.filesData?.forEach((file) => {
      console.log(`Download: ${file.downloadLink}`);
    });
  }
  ```

  ```python PYTHON theme={null}
  from dragdropdo_sdk import Dragdropdo, D3ClientConfig

  client = Dragdropdo(
      api_key="your-api-key",
      base_url="https://api.dragdropdo.com"
  )

  # Poll until completion
  status = client.poll_status(
      main_task_id="task_abc123",
      interval=2000,  # Check every 2 seconds
      on_update=lambda s: print(f"Status: {s.operation_status}")
  )

  if status.operation_status == "completed":
      for file in status.files_data:
          print(f"Download: {file.download_link}")
  ```

  ```php PHP theme={null}
  use DragdropdoSdk\Dragdropdo;

  $client = new Dragdropdo([
      'api_key' => 'your-api-key',
      'base_url' => 'https://api.dragdropdo.com',
  ]);

  // Poll until completion
  $status = $client->pollStatus([
      'main_task_id' => 'task_abc123',
      'interval' => 2000, // Check every 2 seconds
      'on_update' => function($status) {
          echo "Status: " . $status['operation_status'] . "\n";
      },
  ]);

  if ($status['operation_status'] === 'completed') {
      foreach ($status['files_data'] as $file) {
          echo "Download: " . $file['download_link'] . "\n";
      }
  }
  ```

  ```ruby RUBY theme={null}
  require 'dragdropdo_sdk'

  client = DragdropdoSdk::Dragdropdo.new(
    api_key: 'your-api-key',
    base_url: 'https://api.dragdropdo.com'
  )

  # Poll until completion
  status = client.poll_status(
    main_task_id: 'task_abc123',
    interval: 2000, # Check every 2 seconds
    on_update: ->(s) { puts "Status: #{s[:operation_status]}" }
  )

  if status[:operation_status] == 'completed'
    status[:files_data].each do |file|
      puts "Download: #{file[:download_link]}"
    end
  end
  ```

  ```go GO theme={null}
  import "github.com/d3/dragdropdo-sdk-go"
  import "time"

  client, _ := d3.NewDragdropdo(d3.Config{
      APIKey:  "your-api-key",
      BaseURL: "https://api.dragdropdo.com",
  })

  // Poll until completion
  status, _ := client.PollStatus(d3.PollStatusOptions{
      StatusOptions: d3.StatusOptions{
          MainTaskID: "task_abc123",
      },
      Interval: 2 * time.Second, // Check every 2 seconds
      OnUpdate: func(s d3.StatusResponse) {
          fmt.Printf("Status: %s\n", s.OperationStatus)
      },
  })

  if status.OperationStatus == "completed" {
      for _, file := range status.FilesData {
          fmt.Printf("Download: %s\n", file.DownloadLink)
      }
  }
  ```

  ```java JAVA theme={null}
  import com.dragdropdo.sdk.Dragdropdo;
  import com.dragdropdo.sdk.DragdropdoConfig;
  import com.dragdropdo.sdk.models.*;

  Dragdropdo client = new Dragdropdo(
      new DragdropdoConfig("your-api-key")
          .setBaseUrl("https://api.dragdropdo.com")
  );

  // Poll until completion
  StatusResponse status = client.pollStatus(
      new PollStatusOptions()
          .setMainTaskId("task_abc123")
          .setInterval(2000) // Check every 2 seconds
          .setOnUpdate(s -> System.out.println("Status: " + s.getOperationStatus()))
  );

  if ("completed".equals(status.getOperationStatus())) {
      status.getFilesData().forEach(file ->
          System.out.println("Download: " + file.getDownloadLink())
      );
  }
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "operation_status": "completed",
  "files_data": [
    {
      "file_key": "file_key_123_result",
      "status": "completed",
      "download_link": "/v1/download/file_key_123_result"
    }
  ]
}
```

For production integrations we recommend configuring **webhooks** instead of / in addition to polling. See **Business API → Webhooks**.
