While both APIs generate text, they differ in structure, defaults, and capabilities:
Structural Differences
| Aspect | Chat Completions | Responses API |
|---|---|---|
| Input field | messages (array) | input (string or array) |
| System prompt | {"role": "system"} | instructions parameter |
| Output access | choices[0].message.content | output_text (convenience) |
| Storage default | false | true |
| Multi-turn | Manual message array | previous_response_id |
Three concrete differences you'll notice immediately
(1) response.output_text exists on Responses and is the assistant's final string — no more completion.choices[0].message.content. (2) previous_response_id replaces resending the message array. (3) instructions= at the top level replaces the system-role message. Each is small; together they're a noticeably tighter shape.
The migration cost is dominated by tool-shape differences — see Custom Function Tools below for the top-level name/parameters vs nested function trap.