How to fix a 401 error received when executing the actions.run function in Pipedream for creating a draft in Gmail?

post by user-1 on Sep 11, 2025

This topic was automatically generated from Slack. You can find the original thread here.

Hi Team,

I am trying to use tool calling to create draft in my gmail. Below is the snippet I am trying to use:

from pipedream import Pipedream
from infrastructure.config.settings import get_settings

def create_draft(user_email: str, to: str, subject: str, body: str):
    try:
        settings = get_settings()
        pipedream_client = Pipedream(
            client_id=settings.pipedream_client_id,
            client_secret=settings.pipedream_client_secret,
            project_environment=settings.pipedream_environment,
            project_id=settings.pipedream_project_id
        )
        accounts = pipedream_client.accounts.list()
        account = next((account for account in accounts if account.external_id == user_email), None)
        execute_tool_response = pipedream_client.actions.run(
            id="gmail-create-draft",
            external_user_id=user_email,
            configured_props={{ "to": to, "subject": subject, "body": body, "from_email": user_email, "gmail": {{
                "auth_provision_id": account.id
                }}
            }},
        )
    except Exception as e:
        return str(e)
    return execute_tool_response

But, when executing the actions.run, it’s giving me 401. By looking into the error message, it looks like that token it’s generated expires on “Mon, 01 Jan 1990 00:00:00 GMT”. Please help fixing the issue. Thanks in advance. Also attaching the full error message json.

post by user-1 on Sep 11, 2025

Hey ,

external_user_id=user_email,

Your external_user_id looks weird, the external user id usually be the uuid, for example

demo-39570d3e-7db3-43ed-8259-3faf1a6dec2c

post by user-1 on Sep 11, 2025

Thanks a lot for supporting me. But the issue is still not resolved. I am getting the same error. Here’s what changed.

  1. Changed the external user id to proper format:
  2. Changed the code to accommodate the above change:
def create_draft(user_email: str, to: str, subject: str, body: str):
    try:
        settings = get_settings()
        pipedream_client = Pipedream(
            client_id=settings.pipedream_client_id,
            client_secret=settings.pipedream_client_secret,
            project_environment=settings.pipedream_environment,
            project_id=settings.pipedream_project_id
        )
        accounts = pipedream_client.accounts.list()
        account = accounts.items[0]
        execute_tool_response = pipedream_client.actions.run(
            id="gmail-create-draft",
            external_user_id=account.external_id,
            configured_props={{ "to": to, "subject": subject, "body": body, "from_email": user_email, "gmail": {{
                "auth_provision_id": account.id
                }}
            }},
        )
    except Exception as e:
        return str(e)
    return execute_tool_response

post by user-1 on Sep 11, 2025

Hey, my suggestion is that you can try to use Pipedream Connect with Pipedream Typescript SDK first to understand how it works first. Then you can switch to Python once you understand everything.

post by user-1 on Sep 11, 2025

See the detailed demo here: https://pipedream-connect-demo.vercel.app/connect/demo

post by user-1 on Sep 11, 2025

Thanks, to test the connect functionality do I have to test it all in the UI? Can I not add a user from nextjs UI and then invoke the tool as a python function? I am trying to highlight:

Why is the token having expiry in 1990? What can cause this? Is it a bug in the python API?

post by user-1 on Sep 11, 2025

PS: In the snippet I attached, pipedream_client.accounts.list() works. But, pipedream_client.actions.run gives me the error and the actions run is the python equivalent of what is found at: One SDK, thousands of API integrations

Few more pointers:

  1. I am in Pipedream free plan.
  2. If I need to upgrade to another plan, just to test out Pipedream will work for my use case or not, what is the plan I need to go for?

post by user-1 on Sep 11, 2025

I wonder if the connected account for Gmail is maybe not working, since it doesn’t sound like you’re getting a 401 from Pipedream; it sounds like the 401 is maybe coming from Gmail. Can you also try listing that account and checking account.healthy and account.dead for that Gmail account?

post by user-1 on Sep 11, 2025

Thanks Danny, but I am currently using curl command to invoke the action and it works. Which proves there's no issue with my Gmail/Outlook account. I keep getting 401 when using the Python API only.

post by user-1 on Sep 11, 2025

Can you show me your cURL command? Do other action executions work?

post by user-1 on Sep 11, 2025

I have tried Gmail and Outlook find mail and create draft actions which work using curl but not using the Python scripts: The details mentioned here: Slack

post by user-1 on Sep 11, 2025

Interesting, I can reproduce your issue. I cannot however reproduce it across all actions; for example, actions.run() works for me for google_sheets-list-worksheets, so I’m trying some other Gmail actions now.

post by user-1 on Sep 11, 2025

Hm actually it might’ve been an error with my environment, it’s working end to end for me. Here’s my full code snippet:

import os
import json
from dotenv import load_dotenv
from pipedream import Pipedream

load_dotenv()

client = Pipedream(
  project_id=os.getenv("PIPEDREAM_PROJECT_ID"),
  project_environment=os.getenv("PIPEDREAM_ENVIRONMENT"),
  client_id=os.getenv("PIPEDREAM_CLIENT_ID"),
  client_secret=os.getenv("PIPEDREAM_CLIENT_SECRET"),
)

external_user_id = os.getenv("EXTERNAL_USER_ID")
account_id = os.getenv("ACCOUNT_ID")
configured_props = {{
  "gmail": {{
    "authProvisionId": account_id
  }},
  "to": "[danny@pipedream.com](mailto:danny@pipedream.com)",
  "subject": "Hello, world!",
  "body": "This is a test"
}}
payload = {{
  "external_user_id": external_user_id,
  "id": "gmail-create-draft",
  "configured_props": configured_props
}}

print("=== REQUEST PAYLOAD ===")
print(f"external_user_id: {external_user_id}")
print(f"payload: {json.dumps(payload, indent=2)}")
print("=====================
")

response = client.actions.run(
  external_user_id=external_user_id,
  id="gmail-create-draft",
  configured_props=configured_props
)
print(json.dumps(response, indent=2, default=str))

post by user-1 on Sep 11, 2025

I really started working. Your example and my example both are working !!

post by user-1 on Sep 11, 2025

Weird, no changes on your end?