API call failed: 400 Client Error: Bad Request for url


Im Stuck…

I will say from the getgo that I am not a coder. Im simply someone who has been creating scripts in Chat GPT tp create small standalone apps that I can use in my small retail space to expidite a few processes that are either time consuming, mundane or both. Its been a fascinating process and I have learnt a lot.

Im currently working on my most complicated endevour yet… which I am certain would be small fry for you all… but for me I have hit a brick wall.

The app / script is meant to grab a .eml file, and then create a list of the attachments within the gui, convert them to webp, resize and save to a predetermined fold. That bit works. It then grabs the text content from that email including the sender and the subject, and then creates a new text file that is prepended with my master prompt, send to the API, and then return a tabulated spreadsheet compatible CSV file back.

Now, when I use that prepended prompt and email body text (which we shall refer to as the reference text body), via the everyday ChatGPT plus web interface, it works like a charm. I copy the response directly into a spreadsheet and I save so much time.

The same prompt, sent via the API just gives me **API call failed: 400 Client Error: Bad Request for url

My API key is valid. I beleive I have more than enough tokens to run this again and again. My credentials work if use the same credentials in a new GUI that I can ask a question, like what color was Mace Windu’s Lightsaber, and get the response back in the requested file format. So something I am doing is wrong and wholly not obvious to me.

What I am trying to do is get these tools up and running so that I can reclaim some of the work life balance that is so easily lost when running a small owner operated retail venture.

Wondering if there is any help or guidence you may be able to offer… bearing in mind that I am not a programmer… I do not code. B

Can you share your code? Also if you look at the response body you receive back it should have more information about what the specific error is

certainly, and thanks for responding…

import tkinter as tk
from tkinter import filedialog, messagebox
import email
import os
from PIL import Image
from io import BytesIO
import webptools
import csv
import json
import requests
import subprocess

checkbox_vars = # Declare checkbox_vars as a global variable
attachments = # Declare attachments as a global variable
email_subject = “” # Declare email_subject as a global variable
msg = None # Declare msg as a global variable

def process_email(file_path):
global attachments, email_subject, msg

with open(file_path, 'r', encoding='utf-8') as file:
    msg = email.message_from_file(file)
    email_subject = msg['Subject']

    print("Email Subject:", email_subject)
    print("Email From:", msg['From'])
    print("Email To:", msg['To'])
    print("Email Body:")
    if msg.is_multipart():
        for part in msg.walk():
            content_type = part.get_content_type()
            disposition = str(part.get('Content-Disposition'))

            if content_type == 'text/plain' and 'attachment' not in disposition:

    attachments = []
    for part in msg.walk():
        content_type = part.get_content_type()
        disposition = str(part.get('Content-Disposition'))

        if 'attachment' in disposition:
            filename = part.get_filename()
            if filename:

    if attachments:
        for attachment in attachments:
        print("No attachments found.")

def select_file():
global file_path
file_path = filedialog.askopenfilename(filetypes=[(‘Email Files’, ‘*.eml’)])
if file_path:

def save_attachments():
global msg # Access the global msg variable

selected_attachments = []
for checkbox_var, attachment in zip(checkbox_vars, attachments):
    if checkbox_var.get() == 1:  # Check if the variable's value is 1 (selected)

if selected_attachments:
    folder_name = email_subject.replace("/", "-")  # Replace invalid characters in subject for folder name
    folder_path = os.path.join(os.getcwd(), folder_name)
    os.makedirs(folder_path, exist_ok=True)

    for attachment in selected_attachments:
        attachment_path = os.path.join(folder_path, attachment)
        with open(attachment_path, 'wb') as file:
            # Retrieve the attachment content from the email message
            for part in msg.walk():
                content_type = part.get_content_type()
                disposition = str(part.get('Content-Disposition'))

                if disposition and 'attachment' in disposition and part.get_filename() == attachment:
                    attachment_content = part.get_payload(decode=True)
                    if attachment_content:
                        # Save the attachment as an image with size constraints
                        image = Image.open(BytesIO(attachment_content))
                        image.thumbnail((600, 600), Image.LANCZOS)
                        image.save(file, format='JPEG', quality=90)  # Save as JPEG format

                        # Convert the saved JPEG image to WebP format using Pillow
                        webp_path = attachment_path.replace(".jpg", ".webp")
                        image.save(webp_path, format='WebP', quality=90)

    print("Attachments saved to:", folder_path)
    print("No attachments selected.")

def update_attachments_report():
for widget in attachments_frame.winfo_children():

global checkboxes, checkbox_vars
checkboxes = []
checkbox_vars = []

if attachments:
    attachments_label = tk.Label(attachments_frame, text="Attachments:")

    for attachment in attachments:
        checkbox_var = tk.IntVar()
        checkbox = tk.Checkbutton(attachments_frame, text=attachment, variable=checkbox_var)

    no_attachments_label = tk.Label(attachments_frame, text="No attachments found.")

def create_prompt():
# Check if an email has been processed
if msg is None:
messagebox.showerror(“Error”, “No email file selected.”)

prompt_content = ""  # Initialize the prompt content

# Read the content of the MasterPrompt file
prompt_folder = "PROMPT"
master_prompt_file = os.path.join(prompt_folder, "MasterPrompt.txt")
with open(master_prompt_file, 'r', encoding='utf-8') as file:
    prompt_content += file.read()  # Append the MasterPrompt content

email_content = ""
if msg.is_multipart():
    for part in msg.walk():
        content_type = part.get_content_type()
        disposition = str(part.get('Content-Disposition'))

        if content_type == 'text/plain' and 'attachment' not in disposition:
            email_content += part.get_payload(decode=True).decode()
    email_content = msg.get_payload()

# Append the email content to the prompt
prompt_content += "\n" + email_content

# Write the prompt content to the prompt file
to_chat_folder = "TO_CHAT"
os.makedirs(to_chat_folder, exist_ok=True)
prompt_file_path = os.path.join(to_chat_folder, "prompt.txt")
with open(prompt_file_path, 'w', encoding='utf-8') as file:

messagebox.showinfo("Success", "Prompt created.")

def send_to_api():
# Check if a prompt file exists
prompt_file_path = os.path.join(“TO_CHAT”, “prompt.txt”)
if not os.path.isfile(prompt_file_path):
messagebox.showerror(“Error”, “Prompt file not found.”)

# Read the prompt content from the file
with open(prompt_file_path, 'r', encoding='utf-8') as file:
    prompt_content = file.read()

# Call the ChatGPT API to process the prompt
api_key = "0000"  # Replace with your actual API key. I have removed mine
api_url = "https://api.openai.com/v1/chat/completions"
headers = {
    "Authorization": f"Bearer {api_key}",
    "Content-Type": "application/json"
data = {
    "prompt": prompt_content,
    "max_tokens": 100,
    "n": 1

    response = requests.post(api_url, headers=headers, json=data)

    response_json = response.json()

    if "choices" in response_json:
        choices = response_json["choices"]
        if choices:
            completion = choices[0]["text"]
            # Handle the completion as per your requirements
            messagebox.showinfo("Success", "Prompt processed.")
            messagebox.showinfo("Info", "No completion received from the API.")
        messagebox.showerror("Error", "Unexpected response format.")

except requests.exceptions.HTTPError as e:
    error_message = str(e)
    messagebox.showerror("Error", f"API call failed: {error_message}")

except requests.exceptions.RequestException as e:
    error_message = str(e)
    messagebox.showerror("Error", f"An error occurred: {error_message}")

def log_error(error_message):
log_folder = “LOGS”
os.makedirs(log_folder, exist_ok=True)
log_file = os.path.join(log_folder, “error_log.txt”)

with open(log_file, "a", encoding="utf-8") as file:
    file.write(f"Error: {error_message}\n")

Create the GUI window

window = tk.Tk()
window.configure(bg=‘dark grey’)

Create the select file button

select_file_button = tk.Button(window, text=‘Select .eml File’, command=select_file, bd=1, relief=‘solid’, fg=‘red’)

Create the attachments report canvas

attachments_canvas = tk.Canvas(window, bg=‘white’)
attachments_canvas.pack(fill=tk.BOTH, expand=True, side=tk.LEFT)

Create the attachments report frame

attachments_frame = tk.Frame(attachments_canvas, bg=‘white’)
attachments_frame.pack(fill=tk.BOTH, expand=True)

Create the attachments report scrollbar

attachments_scrollbar = tk.Scrollbar(window, command=attachments_canvas.yview)
attachments_scrollbar.pack(fill=tk.Y, side=tk.RIGHT)

attachments_canvas.create_window((0, 0), window=attachments_frame, anchor=tk.NW)

Create the Save Attachments button

save_attachments_button = tk.Button(window, text=‘Save Attachments’, command=save_attachments, bd=1, relief=‘solid’, fg=‘red’)

Create the Create Prompt button

create_prompt_button = tk.Button(window, text=‘Create Prompt’, command=create_prompt, bd=1, relief=‘solid’, fg=‘green’)

Create the Teleport button

teleport_button = tk.Button(window, text=‘Teleport’, command=send_to_api, bd=1, relief=‘solid’, fg=‘blue’)

Start the GUI event loop


This code is wrong. You aren’t specifying a model, and you are using the ChatCompletion endpoint but with the Completion request body. Take a look at the API Reference

thanks Nova… I have looked at the API, but i am not a coder. I have put this altogether via chats with chat gpt, and testing.

is there anyone out there willing to help me correct this, please? These are unchartered waters as far as I am concerned.


There’s a lot of code to wade through here, and a pretty daunting task for a non-developer.

But if you are trying to use GPT3.5 Your data object needs to look like something this:

  "model": "gpt-3.5-turbo",
  "messages": [{"role": "user", "content": prompt_content}]

Thanks. Only just saw your message. Managed to succesfully hook into the API at the weekend, and everything works as it should, bar the token allowance. So back to the drawing board to streamline…