Alteryx IO Discussions

Customize and extend the power of Alteryx with SDKs, APIs, custom tools, and more.

Post workflow to 2023.2 api

12 - Quasar

I'm creating a Python wrapper for the Server API using HTTPX as the Python library for web queries.

When implementing the workflow post method I'm getting a 415 error indicating a media type error. If I test the same code using requests the process works and I have mapped it across to httpx correctly (I think), but I can't find why the 415 error is being produced. I think it is due to the way the file is being presented to the API but i cant identify what is incorrect. Any assistance would be appreciated


The code I'm using to post the workflow is: (full code on github)


from pathlib import Path
from typing import Any, Dict, Optional, Tuple

import httpx

def _post(
    self, endpoint: str, params: Optional[Dict[str, Any]] = None, **kwargs
) -> Tuple[httpx.Response, Dict[str, Any]]:
    params = params or {}  # Ensure params is a dictionary
    endpoint = endpoint.lstrip("/")  # Remove leading slash if present
    response =
        f"{self.base_url}/{endpoint}", params=params, **kwargs
    return response, response.json()

def post_publish_workflow(
    file_path: Path,
    name: str,
    owner_id: str,
    is_public: bool = False,
    is_ready_for_migration: bool = False,
    others_may_download: bool = True,
    others_can_execute: bool = True,
    execution_mode: str = "Standard",
    workflow_credential_type: str = "Default",
) -> Tuple[httpx.Response, Dict[str, Any]]:
    file_path = Path(file_path)

    ## Removed Validation Code for brevity

    data = {
        "name": name,
        "ownerId": owner_id,
        "isPublic": is_public,
        "isReadyForMigration": is_ready_for_migration,
        "othersMayDownload": others_may_download,
        "othersCanExecute": others_can_execute,
        "executionMode": execution_mode,
        "workflowCredentialType": workflow_credential_type,

    # Add keyword arguments to the data dictionary
    for key, value in kwargs.items():
        data[key] = value

    # Update the authorization header
    # Make the POST request
    with open(file_path, "rb") as file:
        # content_file = file
        files = {"file": (, file, "application/yxzp")}
        headers = {
            "Content-Type": "application/x-www-form-urlencoded",  # "multipart/form-data",
        headers["Accept"] = "application/json"

        response = self._post(
        return response




Hi Paul,


Thanks for reaching out for assistance with the issue you are experiencing. While I do not have direct experience with the HTTPX Python library, using the code you supplied I reviewed the request using Fiddler (screenshot below) and noticed a few possible issues with the format of the request.


The first is that the Content-Type header is set to application/x-www-form-urlencoded. The Content-Type header should be multipart/form-data and it also needs to include a boundary definition. I have included an example below of what the Content-Header should look like, this is what I see in Fiddler when using the Server API tool to publish a workflow. I believe the HTTPX library will automatically set the content-type and generate the boundary if you remove "Content-Type": "application/x-www-form-urlencoded", # "multipart/form-data", from your code. 


Content-Type: multipart/form-data; boundary=15fb84fc67e41719d3ff120cafca795c



Another possible issue is that the filename in the form-data contains the full path to the file, rather than just the name of the file. The following is an example of what I see in Fiddler:


Content-Disposition: form-data; name="file"; filename="C:\\temp\\Generate Rows_API Publish.yxzp"
Content-Type: application/yxzp


I would recommend changing the filename so it's just the actual file name. In the case of the example above, the filename would be "Generate Rows_API Publish". The extension is not required, but the request should still work if it is included.

12 - Quasar

Hi @ZacharyH Thanks for the reply.


I wasn't able to find the issue in HTTPX so I tried the process in requests (postman provides an example script that works to modify) and discovered the following


I looked into the Content-Type and that header is not actually needed at all, removing that header clears the 415 error and is managed internally in the package.


The file name is my underlying problem, I was generating the file name from the open file context manager. What I didn't realise was the from that property was the name is the full path description, not the Pathlib file name. changing the context manager section to:


with open(file_path, "rb") as file:
        # content_file = file
        files = {"file": (, file, "application/octet-stream")}


Allowed me to successfully publish the workflow. now to translate the learning to using httpx.