# Complete an upload

> After a successful PUT, POST the returned completion_url before expires_at. The token authorizes only this Upload; no API key, cookies, or request body is required. Verifies the stored object and commits one Source relationship. Valid retries return 204 without duplicate side effects. Retry network errors, 429, and 5xx responses with bounded backoff; never repeat the PUT just to retry completion.

```json
{
  "path": "/api/uploads/completion/{token}",
  "method": "post",
  "schema": {
    "description": "After a successful PUT, POST the returned completion_url before expires_at. The token authorizes only this Upload; no API key, cookies, or request body is required. Verifies the stored object and commits one Source relationship. Valid retries return 204 without duplicate side effects. Retry network errors, 429, and 5xx responses with bounded backoff; never repeat the PUT just to retry completion.",
    "operationId": "completeUpload",
    "parameters": [
      {
        "description": "Opaque completion capability from completion_url",
        "in": "path",
        "name": "token",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    ],
    "responses": {
      "204": {
        "description": "Upload completed or already completed. The response body is empty."
      },
      "400": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ResponseErrorValidation"
            }
          }
        },
        "description": "Invalid uploaded media or Upload is no longer waiting"
      },
      "401": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ResponseErrorAuthentication"
            }
          }
        },
        "description": "Invalid completion capability"
      },
      "403": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ResponseErrorForbidden"
            }
          }
        },
        "description": "Storage permission or plan limit prevents completion"
      },
      "410": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ResponseErrorGone"
            }
          }
        },
        "description": "Upload session expired or was deleted"
      },
      "429": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ResponseErrorTooManyRequests"
            }
          }
        },
        "description": "Rate limited; retry with backoff"
      },
      "503": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ResponseErrorServiceUnavailable"
            }
          }
        },
        "description": "Temporary object verification failure; retry completion"
      }
    },
    "security": [],
    "summary": "Complete an upload",
    "tags": [
      "Uploads"
    ],
    "x-codeSamples": [
      {
        "lang": "JavaScript",
        "source": "// Use the completion_url returned when creating the Upload.\nconst response = await fetch(upload.completion_url, {\n  method: 'POST',\n  credentials: 'omit',\n});\nif (!response.ok) {\n  throw new Error(`Completion failed: ${response.status}`);\n}\n// 204 No Content: do not call response.json()."
      },
      {
        "lang": "Python",
        "source": "import requests\n\n# Use the completion_url returned when creating the Upload.\nresponse = requests.post(upload[\"completion_url\"], timeout=30)\nresponse.raise_for_status()\n# 204 No Content: there is no JSON response to parse."
      },
      {
        "lang": "php",
        "source": "\u003c?php\n\n// Use the completion_url returned when creating the Upload.\n$request = curl_init($upload['completion_url']);\ncurl_setopt_array($request, [\n    CURLOPT_POST =\u003e true,\n    CURLOPT_RETURNTRANSFER =\u003e true,\n    CURLOPT_TIMEOUT =\u003e 30,\n]);\n$result = curl_exec($request);\n$status = curl_getinfo($request, CURLINFO_HTTP_CODE);\nif ($result === false || $status !== 204) {\n    throw new RuntimeException('Completion failed: ' . $status);\n}\ncurl_close($request);\n// 204 No Content: there is no JSON response to parse."
      },
      {
        "lang": "Go",
        "source": "// completionURL is the completion_url returned when creating the Upload.\nreq, err := http.NewRequestWithContext(ctx, http.MethodPost, completionURL, nil)\nif err != nil {\n    return err\n}\nclient := \u0026http.Client{Timeout: 30 * time.Second}\nresp, err := client.Do(req)\nif err != nil {\n    return err\n}\ndefer resp.Body.Close()\nif resp.StatusCode != http.StatusNoContent {\n    return fmt.Errorf(\"completion failed: %d\", resp.StatusCode)\n}\n// 204 No Content: there is no JSON response to decode."
      }
    ]
  }
}
```



```json #/components/schemas/ResponseErrorServiceUnavailable
{
  "properties": {
    "error": {
      "description": "Error response details",
      "properties": {
        "code": {
          "const": 503,
          "description": "Code is the HTTP status code",
          "examples": [
            503
          ],
          "type": "integer"
        },
        "message": {
          "description": "Message is a human-readable error description",
          "examples": [
            "The service is temporarily unavailable; retry the request"
          ],
          "type": "string"
        },
        "type": {
          "const": "ServiceUnavailableError",
          "description": "Type indicates the error category",
          "enum": [
            "ServiceUnavailableError"
          ],
          "type": "string"
        }
      },
      "required": [
        "type",
        "code",
        "message"
      ],
      "type": "object"
    },
    "status": {
      "const": "error",
      "description": "Status indicates the response status \"error\"",
      "type": "string"
    }
  },
  "required": [
    "status",
    "error"
  ]
}
```



```json #/components/schemas/ResponseErrorValidation
{
  "properties": {
    "error": {
      "properties": {
        "code": {
          "const": 400,
          "description": "Code is the HTTP status code",
          "examples": [
            400
          ],
          "type": "integer"
        },
        "message": {
          "description": "Message is a human-readable error description",
          "examples": [
            "Invalid request parameters"
          ],
          "type": "string"
        },
        "type": {
          "const": "ValidationError",
          "description": "Type indicates the error category",
          "enum": [
            "ValidationError"
          ],
          "type": "string"
        }
      },
      "required": [
        "type",
        "code",
        "message"
      ],
      "type": "object"
    },
    "status": {
      "const": "error",
      "description": "Status indicates the response status \"error\"",
      "type": "string"
    }
  },
  "required": [
    "status",
    "error"
  ]
}
```



```json #/components/schemas/ResponseErrorAuthentication
{
  "description": "Error response",
  "properties": {
    "error": {
      "description": "Error response details",
      "properties": {
        "code": {
          "const": 401,
          "description": "Code is the HTTP status code",
          "examples": [
            401
          ],
          "type": "integer"
        },
        "message": {
          "description": "Message is a human-readable error description",
          "examples": [
            "Authentication error: invalid token or subscription inactive"
          ],
          "type": "string"
        },
        "type": {
          "const": "AuthenticationError",
          "description": "Type indicates the error category",
          "enum": [
            "AuthenticationError"
          ],
          "type": "string"
        }
      },
      "required": [
        "type",
        "code",
        "message"
      ],
      "type": "object"
    },
    "status": {
      "const": "error",
      "description": "Status indicates the response status \"error\"",
      "type": "string"
    }
  },
  "required": [
    "status",
    "error"
  ],
  "type": "object"
}
```



```json #/components/schemas/ResponseErrorForbidden
{
  "properties": {
    "error": {
      "description": "Error response details",
      "properties": {
        "code": {
          "const": 403,
          "description": "Code is the HTTP status code",
          "examples": [
            403
          ],
          "type": "integer"
        },
        "message": {
          "description": "Message is a human-readable error description",
          "examples": [
            "Unauthorized to perform this action"
          ],
          "type": "string"
        },
        "type": {
          "const": "ForbiddenError",
          "description": "Type indicates the error category",
          "enum": [
            "ForbiddenError"
          ],
          "type": "string"
        }
      },
      "required": [
        "type",
        "code",
        "message"
      ],
      "type": "object"
    },
    "status": {
      "const": "error",
      "description": "Status indicates the response status \"error\"",
      "type": "string"
    }
  },
  "required": [
    "status",
    "error"
  ]
}
```



```json #/components/schemas/ResponseErrorGone
{
  "properties": {
    "error": {
      "description": "Error response details",
      "properties": {
        "code": {
          "const": 410,
          "description": "Code is the HTTP status code",
          "examples": [
            410
          ],
          "type": "integer"
        },
        "message": {
          "description": "Message is a human-readable error description",
          "examples": [
            "The requested resource is no longer available"
          ],
          "type": "string"
        },
        "type": {
          "const": "GoneError",
          "description": "Type indicates the error category",
          "enum": [
            "GoneError"
          ],
          "type": "string"
        }
      },
      "required": [
        "type",
        "code",
        "message"
      ],
      "type": "object"
    },
    "status": {
      "const": "error",
      "description": "Status indicates the response status \"error\"",
      "type": "string"
    }
  },
  "required": [
    "status",
    "error"
  ]
}
```



```json #/components/schemas/ResponseErrorTooManyRequests
{
  "description": "Error response",
  "properties": {
    "error": {
      "description": "Error response details",
      "properties": {
        "code": {
          "const": 429,
          "description": "Code is the HTTP status code",
          "examples": [
            429
          ],
          "type": "integer"
        },
        "message": {
          "description": "Message is a human-readable error description",
          "examples": [
            "Rate limit exceeded"
          ],
          "type": "string"
        },
        "type": {
          "const": "TooManyRequestsError",
          "description": "Type indicates the error category",
          "enum": [
            "TooManyRequestsError"
          ],
          "type": "string"
        }
      },
      "required": [
        "type",
        "code",
        "message"
      ],
      "type": "object"
    },
    "status": {
      "const": "error",
      "description": "Status indicates the response status \"error\"",
      "type": "string"
    }
  },
  "required": [
    "status",
    "error"
  ],
  "type": "object"
}
```