Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 29 additions & 15 deletions peps/pep-0694.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ In addition, there are a number of major issues with the legacy API:

The new upload API proposed in this PEP provides ways to solve all of these problems, either directly or
through an extensible approach, allowing servers to implement features such as resumable and parallel uploads.
This upload API this PEP proposes provides better error reporting, a more robust release testing experience,
and atomic and simultaneous publishing of all release artifacts.
This upload API this PEP proposes provides better and more standardized error reporting, a more robust release
testing experience, and atomic and simultaneous publishing of all release artifacts.

Legacy API
==========
Expand Down Expand Up @@ -274,17 +274,26 @@ are determined by the index operator.
Errors
------

Unless otherwise specified, all error (4xx and 5xx) responses from the server **MUST** use the :rfc:`9457`
(Problem Details for HTTP APIs) format. In particular, the server **MUST** use the "Problem Details JSON
Object" defined in :rfc:`Section 3 <9457#section-3>` and **SHOULD** use the ``application/problem+json`` media
type in its responses.

Clients in general should be prepared to handle `HTTP response error status codes
<https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status>`_ which **MAY** contain payloads of the
the following format:
<https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status>`_ which **SHOULD** contain payloads like
the following, although note that the details are index-specific, as long as they conform to RFC 9457. By way
of example, PyPI could return the following error body:

.. code-block:: json

{
"type": "https://docs.pypi.org/api/errors/error-types#invalid-filename",
"status": 400,
"title": "The artifact used an invalid wheel file name format",
"details": "See https://packaging.python.org/en/latest/specifications/binary-distribution-format/",
"meta": {
"api-version": "2.0"
},
"message": "...",
"errors": [
{
"source": "...",
Expand All @@ -293,11 +302,12 @@ the following format:
]
}

Besides the standard ``meta`` key, this has the following top level keys:
RFC 9457 defines ``type``, ``status``, ``title``, and ``details``. The ``meta`` and ``errors`` keys are
"extension members", defined in :rfc:`Section 3.2 <9457#section-3.2>`. The index **SHOULD** include these
extension members.

``message``
A singular message that encapsulates all errors that may have happened on this
request.
``meta``
The same request/response metadata structure as defined in the :ref:`publishing-session` description.

``errors``
An array of specific errors, each of which contains a ``source`` key, which is a string that
Expand Down Expand Up @@ -683,14 +693,14 @@ The request looks like:
Besides the standard ``meta`` key, the request JSON has the following additional keys:

``filename`` (**required**)
The name of the file being uploaded. The filename **MUST** conform to either the `source
distribution file name specification
The name of the file being uploaded. The filename **MUST** conform to either the `source distribution
file name specification
<https://packaging.python.org/en/latest/specifications/source-distribution-format/#source-distribution-file-name>`_
or the `binary distribution file name convention
<https://packaging.python.org/en/latest/specifications/binary-distribution-format/#file-name-convention>`_.
Indexes **SHOULD** validate these file names at the time of the request, returning a ``400 Bad
Request`` error code, as described in the :ref:`session-errors` section when the file names do
not conform.
Indexes **SHOULD** validate these file names at the time of the request, returning a ``400 Bad Request``
error code and an RFC 9457 style error body, as described in the :ref:`session-errors` section when the
file names do not conform.

``size`` (**required**)
The size in bytes of the file being uploaded.
Expand Down Expand Up @@ -1094,7 +1104,11 @@ as experience is gained operating Upload 2.0.
Change History
==============

* `23-Sep-2025 <TBD>`__
* `06-Dec-2025 <TBD>`__

* Error responses conform to the :rfc:`9457` format.

* `23-Sep-2025 <https://discuss.python.org/t/pep-694-pypi-upload-api-2-0-round-2/101483/31>`__

* Remove the ``nonce`` and ``gentoken()`` algorithm. Indexes are now responsible for generating
an cryptographically secure session token and obfuscated stage URL (but only if they support
Expand Down