Skip to main content
  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
  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:
import { Dragdropdo } from "dragdropdo-sdk";

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

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"
)
use DragdropdoSdk\Dragdropdo;

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

client = DragdropdoSdk::Dragdropdo.new(
  api_key: 'd3_live_xxx', # Your API key from the dashboard
  base_url: 'https://api.dragdropdo.com'
)
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",
})
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")
);
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 for the full request and response schema, authentication, and ETag handling. Official SDKs perform all of these steps when you call uploadFile / upload_file.
# 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 }
    ]
  }'

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
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
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
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
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
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

3. Create an operation

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"
    }
  }'
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);
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)
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";
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]}"
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)
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());
Response:
{
  "main_task_id": "task_abc123"
}

4. Poll for status

# 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

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}`);
  });
}
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}")
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";
    }
}
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
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)
    }
}
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())
    );
}
Response:
{
  "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.