You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FedEx REST API上传PDF报错[1001]:请求输入无效求解决

排查FedEx REST API上传PDF时的1001错误

问题描述

我编写Python脚本通过新版FedEx REST API上传PDF文档时,遇到以下错误:

{
"customerTransactionId": "ETD-Pre-Shipment-Upload_test1",
"errors": {
"code": "1001",
"message": "Invalid request: invalid input : Incoming Request"
}
}

以下是可复现问题的最小代码(需替换FedEx生产环境凭证,同级目录放置file.pdf):

# minimal class for upload docs test
class FedexLabelHelper:
    def __init__(self, fedex_cred):
        self.fedex_cred = fedex_cred
        self.access_token = ""

        return

    # function for retrieving access_token
    def get_access_token(self):
        import json, requests

        url = self.fedex_cred["url_prefix"] + "/oauth/token"

        payload = {
            "grant_type": "client_credentials",
            "client_id": self.fedex_cred["key"],
            "client_secret": self.fedex_cred["password"],
        }

        headers = {"Content-Type": "application/x-www-form-urlencoded"}

        response = requests.request("POST", url, data=payload, headers=headers)
        access_token = json.loads(response.text)["access_token"]
        self.access_token = access_token

 
    # function for uploading PDF document 
    def upload_pdf_document_fedex_script(self):
        import requests, binascii

        fileName = "file.pdf"

        file_content = open(fileName, "rb").read()
        file_content_b64 = binascii.b2a_base64(file_content)
        file_content_b64.decode("cp1250")

        url = self.fedex_cred["doc_url_prefix"] + "/documents/v1/etds/upload"

        payload = {
            "document": {
                "workflowName": "ETDPreshipment",
                "carrierCode": "FDXE",
                "name": fileName,
                "contentType": "application/pdf",
            },
            "meta": {
                "shipDocumentType": "COMMERCIAL_INVOICE",
                "originCountryCode": "DK",
                "destinationCountryCode": "BE",
            },
        }

        files = [
            (
                "attachment",
                (fileName, "file_content_b64", "application/pdf"),
            )
        ]

        headers = {
            "Authorization": f"Bearer {self.access_token}",
            "x-customer-transaction-id": "ETD-Pre-Shipment-Upload_test1",
            "Cookie": "XYZ",
        }

        response = requests.post(url, headers=headers, data=payload, files=files)

        print(response.text)

  
# -----------------------
# setup minimal test of the FedEx Upload Documents REST API
fedex_cred = {
    "production": {
        "url_prefix": "https://apis.fedex.com",
        "doc_url_prefix": "https://documentapi.prod.fedex.com",
        "key": "XYZ",
        "password": "XYZ",
        "freight_account_number": "XYZ",
    },
}

flh = FedexLabelHelper(fedex_cred["production"])
flh.get_access_token()
flh.upload_pdf_document_fedex_script()

排查与修复建议

1. 修复文件内容传递错误

代码中files参数里直接传入字符串"file_content_b64",而非实际的文件内容,这是核心错误。同时手动转base64的操作多余,requests会自动处理multipart格式的文件上传:

  • 移除binascii相关代码,直接读取二进制文件内容
  • 将files中的字符串替换为实际文件内容

2. 清理无效请求头

硬编码的Cookie: XYZ属于无效内容,会干扰请求合法性,直接移除该字段。

3. 规范Payload格式

FedEx的ETD上传接口要求document和meta字段为JSON字符串,需用json.dumps()转换后传入。

4. 增加请求异常检查

获取access_token时,添加response.raise_for_status()确保授权请求成功,避免后续使用无效token。

修改后的代码示例

# minimal class for upload docs test
class FedexLabelHelper:
    def __init__(self, fedex_cred):
        self.fedex_cred = fedex_cred
        self.access_token = ""

    # function for retrieving access_token
    def get_access_token(self):
        import json, requests

        url = self.fedex_cred["url_prefix"] + "/oauth/token"

        payload = {
            "grant_type": "client_credentials",
            "client_id": self.fedex_cred["key"],
            "client_secret": self.fedex_cred["password"],
        }

        headers = {"Content-Type": "application/x-www-form-urlencoded"}

        response = requests.post(url, data=payload, headers=headers)
        response.raise_for_status()  # 检查授权请求是否成功
        access_token = response.json()["access_token"]
        self.access_token = access_token

    # function for uploading PDF document 
    def upload_pdf_document_fedex_script(self):
        import requests, json

        fileName = "file.pdf"

        # 直接读取二进制文件内容
        with open(fileName, "rb") as f:
            file_content = f.read()

        url = self.fedex_cred["doc_url_prefix"] + "/documents/v1/etds/upload"

        # 将嵌套结构转为JSON字符串
        payload = {
            "document": json.dumps({
                "workflowName": "ETDPreshipment",
                "carrierCode": "FDXE",
                "name": fileName,
                "contentType": "application/pdf",
            }),
            "meta": json.dumps({
                "shipDocumentType": "COMMERCIAL_INVOICE",
                "originCountryCode": "DK",
                "destinationCountryCode": "BE",
            }),
        }

        files = [
            ("attachment", (fileName, file_content, "application/pdf"))
        ]

        headers = {
            "Authorization": f"Bearer {self.access_token}",
            "x-customer-transaction-id": "ETD-Pre-Shipment-Upload_test1",
        }

        response = requests.post(url, headers=headers, data=payload, files=files)
        print(f"请求状态码: {response.status_code}")
        print(response.text)

# -----------------------
# setup minimal test of the FedEx Upload Documents REST API
fedex_cred = {
    "production": {
        "url_prefix": "https://apis.fedex.com",
        "doc_url_prefix": "https://documentapi.prod.fedex.com",
        "key": "XYZ",  # 替换为你的生产环境凭证
        "password": "XYZ",
        "freight_account_number": "XYZ",
    },
}

flh = FedexLabelHelper(fedex_cred["production"])
flh.get_access_token()
flh.upload_pdf_document_fedex_script()

额外排查步骤

  • 验证FedEx生产凭证的有效性,确保账号有权限使用ETD预上传接口
  • 检查file.pdf是否完整无损坏,文件大小符合FedEx接口限制
  • 对照FedEx官方文档,确认workflowName、shipDocumentType等字段的取值完全符合要求,无拼写错误
  • 开启requests日志调试,查看实际发送的请求内容,确认格式与API要求一致

内容的提问来源于stack exchange,提问作者mfcss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 15:45:05