Skip to main content

DashScope Python SDK 1.x legacy usage reference

Legacy usage reference and 1.x-to-2.0 migration mapping for the DashScope Python SDK, for existing 1.x projects.

This page is for existing projects still on DashScope Python SDK 1.x. It collects the typical 1.x interface usage in one place and shows the equivalent 2.0 code.
For new projects, use SDK 2.0 directly. 1.x is in frozen maintenance (defect fixes only); 1.x and 2.0 coexist in the same dashscope package (from 2.0.1), so existing code can migrate incrementally without removing 1.x dependencies. The Assistants / Threads / Runs API family has been retired with 1.x and is no longer supported on the server side; do not use it in new code.

Interface migration mapping

Capability1.x interface2.0 interface
Text generationGeneration.call / AioGeneration.callclient.chat.completions.create
Multimodal chatMultiModalConversation.callclient.multimodal.chat.create
Image generationImageSynthesis.call/async_call/fetch/waitclient.images.generate / client.images.jobs.*
Video generationVideoSynthesis.call/async_call/fetch/waitclient.videos.generate / client.videos.jobs.*
Audio file transcriptionTranscription.async_call/fetch/waitclient.audio.asr.transcribe / client.audio.asr.jobs.*
Real-time speech recognitionRecognition.start/send_audio_frame/stopclient.audio.asr.recognize(...) context manager
Speech synthesisSpeechSynthesizer (tts_v2 callback style)client.audio.tts.synthesize/stream/connect
Text embeddingsTextEmbedding.call / BatchTextEmbeddingclient.embeddings.create / client.embeddings.jobs.*
RerankTextReRank.callclient.rerank.create
Agent applicationApplication.callclient.apps.completions.create
File managementFiles.upload/list/get/deleteclient.files.upload/list/get/delete
Model listModels.list/getclient.models.list/get

Client construction and authentication

1.x is configured via module-level globals; 2.0 is configured via Client constructor arguments (priority: constructor > dashscope.settings > environment variables > ~/.dashscope/config.toml).
# 1.x: globals
import dashscope
dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")
dashscope.base_http_api_url = "https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1"
# 2.0: client construction
import dashscope
client = dashscope.Client(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    workspace="{WorkspaceId}",
    region="cn-beijing",
)

Text generation

# 1.x
from dashscope import Generation
response = Generation.call(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    model="qwen-plus",
    messages=messages,
    result_format="message",
)
if response.status_code == 200:
    print(response.output.choices[0].message.content)
else:
    print(f"HTTP status: {response.status_code}")
    print(f"Error code: {response.code}")
    print(f"Error message: {response.message}")
# 2.0
from dashscope.v2 import DashScopeError
try:
    response = client.chat.completions.create(
        model="qwen-plus",
        messages=messages,
    )
    print(response.choices[0].message.content)
except DashScopeError as e:
    print(f"HTTP status: {e.status_code}")
    print(f"Error code: {e.code}")
    print(f"Error message: {e.message}")

Multimodal chat

# 1.x
from dashscope import MultiModalConversation
response = MultiModalConversation.call(
    api_key=os.getenv('DASHSCOPE_API_KEY'),
    model='qwen3-vl-plus',
    messages=[{
        "role": "user",
        "content": [
            {"image": "https://example.com/image.png"},
            {"text": "What is in this picture?"},
        ],
    }])
print(response.output.choices[0].message.content[0]['text'])
# 2.0: content parts shape kept, flat access
response = client.multimodal.chat.create(
    model='qwen3-vl-plus',
    messages=[{
        "role": "user",
        "content": [
            {"image": "https://example.com/image.png"},
            {"text": "What is in this picture?"},
        ],
    }])
print(response.output_text)

Image generation

# 1.x: synchronous call (blocks until done)
from dashscope import ImageSynthesis
rsp = ImageSynthesis.call(api_key=os.getenv("DASHSCOPE_API_KEY"),
                          model=ImageSynthesis.Models.wanx_v1,
                          prompt=prompt,
                          n=1,
                          style='<watercolor>',
                          size='1024*1024')
if rsp.status_code == HTTPStatus.OK:
    for result in rsp.output.results:
        print(result.url)
else:
    print('Failed, status_code: %s, code: %s, message: %s' %
          (rsp.status_code, rsp.code, rsp.message))
# 2.0: generate one-shot (submit and wait); enum classes become strings
job = client.images.generate(
    model="wanx2.1-t2i-turbo",
    prompt=prompt,
    n=1,
    size='1024*1024',
)
for url in job.image_urls:
    print(url)
Step-by-step tasks (1.x async_call/fetch/wait) map to client.images.jobs.create/fetch/wait; task status changes from rsp.output.task_status == 'SUCCEEDED' to job.succeeded.

Video generation

# 1.x
from dashscope import VideoSynthesis
rsp = VideoSynthesis.call(api_key=api_key,
                          model='wan3.0-video',
                          prompt=prompt,
                          resolution="720P",
                          ratio="16:9",
                          duration=15,
                          watermark=True)
if rsp.status_code == HTTPStatus.OK:
    print("video_url:", rsp.output.video_url)
# 2.0
job = client.videos.generate(
    model='wan3.0-video',
    prompt=prompt,
    resolution="720P",
    ratio="16:9",
    duration=15,
    watermark=True,
)
print("video_url:", job.video_url)
In 1.x, VideoSynthesis extend_prompt defaults to True; in 2.0 it is prompt_extend and the default is decided by the server. Calls that relied on the old default must pass prompt_extend=True explicitly.

Audio file transcription

# 1.x: async_call submit + wait
from dashscope.audio.asr import Transcription
task_response = Transcription.async_call(
    model='paraformer-v2',
    file_urls=['{YOUR_AUDIO_URL}'],
    language_hints=['zh', 'en'],
)
transcribe_response = Transcription.wait(task=task_response.output.task_id)
if transcribe_response.status_code == HTTPStatus.OK:
    print(json.dumps(transcribe_response.output, indent=4, ensure_ascii=False))
# 2.0: transcribe one-shot; non-signature parameters go via parameters
job = client.audio.asr.transcribe(
    ['{YOUR_AUDIO_URL}'],
    model='paraformer-v2',
    parameters={'language_hints': ['zh', 'en']},
)
print(json.dumps(job.model_dump(), indent=4, ensure_ascii=False))
Step-by-step control (former async_call + fetch loop) maps to client.audio.asr.jobs.create + a jobs.fetch loop.

Real-time speech recognition

1.x uses callback classes (Recognition + RecognitionCallback); 2.0 uses a context manager + event iteration.
# 1.x (callback style, excerpt)
from dashscope.audio.asr import Recognition
class Callback(RecognitionCallback):
    def on_result(self, result): ...
recognition = Recognition(model='paraformer-realtime-v2', callback=Callback())
recognition.start()
recognition.send_audio_frame(chunk)
recognition.stop()
# 2.0 (event iteration, send and receive concurrently)
from concurrent.futures import ThreadPoolExecutor

def receive_events(rec):
    for event in rec.events():
        print(event)

with client.audio.asr.recognize(
        model='paraformer-realtime-v2',
        format='pcm',
        sample_rate=16000,
) as recognition:
    with ThreadPoolExecutor(max_workers=1) as pool:
        receiver = pool.submit(receive_events, recognition)
        for chunk in iter_pcm_chunks():  # real-time PCM frames provided by the application
            recognition.send_audio_frame(chunk)
        recognition.stop()
        receiver.result()
One-shot local file recognition (1.x Recognition.call(file)) maps to for event in client.audio.asr.recognize_file(path, model=...):.

Speech synthesis

1.x tts_v2 receives audio via callbacks; 2.0 uses iteration/session style.
# 1.x (callback style, excerpt)
from dashscope.audio.tts_v2 import SpeechSynthesizer, ResultCallback
class Callback(ResultCallback):
    def on_data(self, data: bytes): audio.write(data)
synthesizer = SpeechSynthesizer(
    model="cosyvoice-v3-flash",
    voice="longanyang",
    callback=Callback(),
)
synthesizer.streaming_call(text)
synthesizer.streaming_complete()
# 2.0: connect session (segmented input + segmented audio)
with client.audio.tts.connect(
        model="cosyvoice-v3-flash",
        voice="longanyang",
        format="mp3",
) as session:
    session.send_text(text)
    session.flush()
    session.stop()  # End the task and wait for remaining audio
    for chunk in session.audio_chunks():
        audio.write(chunk)
One-shot synthesis uses client.audio.tts.synthesize(text, model=..., voice=...); pure streaming iterates client.audio.tts.stream(text, ...).

Embeddings and rerank

# 1.x
resp = dashscope.TextEmbedding.call(
    model="qwen3.7-text-embedding",
    input="The quality of this clothing is excellent.",
)
if resp.status_code == HTTPStatus.OK:
    print(resp)
# 2.0
resp = client.embeddings.create(
    model="qwen3.7-text-embedding",
    input="The quality of this clothing is excellent.",
)
for item in resp.embeddings:
    print(item.index, len(item.embedding))
Batch embeddings (1.x BatchTextEmbedding) map to client.embeddings.jobs.create/fetch/wait. Rerank TextReRank.call maps to client.rerank.create, with results moving from resp.output.results[i] to resp.results[i].

Agent application calls

# 1.x
from dashscope import Application
response = Application.call(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    app_id='APP_ID',
    prompt='Who are you?')
if response.status_code != HTTPStatus.OK:
    print(f'code={response.status_code}, message={response.message}')
else:
    print(response.output.text)
# 2.0
from dashscope.v2 import DashScopeError
try:
    response = client.apps.completions.create(
        app_id='APP_ID',
        prompt='Who are you?')
    print(response.text)
except DashScopeError as e:
    print(f'code={e.code}, message={e.message}')
Streaming application calls keep the incremental_output parameter (it decides the frame shape); per-frame output moves from response.output.text to partial.text.

Behavioral differences

Beyond interface names, note these behavioral differences when migrating:
  • Error handling: 1.x checks status_code/code on the response; 2.0 raises the DashScopeError family by default (with e.code/e.status_code/e.request_id/e.message). For envelope-style behavior, construct Client(raise_on_error=False).
  • Streaming output: 1.x Generation.call(stream=True) replays the full text on every frame by default (incremental_output=True for deltas); 2.0 streams are always incremental. Bailian applications (apps.completions) keep the incremental_output switch.
  • Async task waiting: 1.x wait waits indefinitely by default and returns an error response on timeout; 2.0 jobs.wait has a default 24-hour budget, exponential backoff polling, and raises on FAILED tasks.
  • Response shape: 1.x wraps payload content under output (response.output.choices[...]); 2.0 is flat (response.choices[...]) with conveniences like resp.output_text and job.succeeded.
  • Non-signature parameters: 2.0 resource methods have closed named signatures; model-specific parameters passed through in 1.x must go via parameters={...} (image materials via extra_input=).