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
相关产品推荐
相关产品推荐

