Seth commited on
Commit
03708bb
·
1 Parent(s): 912d218
Files changed (2) hide show
  1. README.md +2 -1
  2. backend/app/smartlead_client.py +23 -8
README.md CHANGED
@@ -28,7 +28,8 @@ A Hugging Face Space application for generating personalized email outreach sequ
28
  1. Set your API keys as secrets in Hugging Face Spaces:
29
  - Go to Settings → Secrets
30
  - Add `OPENAI_API_KEY` with your OpenAI API key value
31
- - Add `SMARTLEAD_API_KEY` with your Smartlead API key value (optional, for Smartlead integration)
 
32
 
33
  2. The app will automatically:
34
  - Create SQLite database in `/data/emailout.db`
 
28
  1. Set your API keys as secrets in Hugging Face Spaces:
29
  - Go to Settings → Secrets
30
  - Add `OPENAI_API_KEY` with your OpenAI API key value
31
+ - Add `SMARTLEAD_API_KEY` with your Smartlead Admin API key value (required for Smartlead integration)
32
+ - Add `SMARTLEAD_CLIENT_API_KEY` with your Smartlead Client API key value (optional, may be required for certain operations)
33
 
34
  2. The app will automatically:
35
  - Create SQLite database in `/data/emailout.db`
backend/app/smartlead_client.py CHANGED
@@ -10,21 +10,35 @@ class SmartleadClient:
10
 
11
  BASE_URL = "https://server.smartlead.ai/api/v1"
12
 
13
- def __init__(self, api_key: Optional[str] = None):
 
 
 
 
 
 
 
14
  self.api_key = api_key or os.getenv("SMARTLEAD_API_KEY")
 
 
15
  if not self.api_key:
16
- raise ValueError("SMARTLEAD_API_KEY environment variable is required (use Admin API key)")
17
 
18
- # Smartlead API authentication - try Bearer token format first
19
- # If that doesn't work, may need to use API key directly or in different header
20
  self.headers = {
21
- "Authorization": f"Bearer {self.api_key}",
22
  "Content-Type": "application/json"
23
  }
24
 
25
  def _make_request(self, method: str, endpoint: str, data: Optional[Dict] = None, max_retries: int = 3) -> Dict:
26
  """Make API request with retry logic for 429/5xx errors"""
27
- url = f"{self.BASE_URL}{endpoint}"
 
 
 
 
 
 
28
 
29
  for attempt in range(max_retries):
30
  try:
@@ -43,7 +57,7 @@ class SmartleadClient:
43
  error_msg = error_data.get('message') or error_data.get('error') or response.text or "Unauthorized"
44
  except:
45
  error_msg = response.text or "Unauthorized"
46
- raise Exception(f"Smartlead API authentication failed (401): {error_msg}. Please verify you're using the Admin API key (not Client API key) and that it's correctly set in SMARTLEAD_API_KEY environment variable.")
47
 
48
  # Handle rate limiting
49
  if response.status_code == 429:
@@ -63,7 +77,8 @@ class SmartleadClient:
63
 
64
  except requests.exceptions.HTTPError as e:
65
  if response.status_code == 401:
66
- raise Exception(f"Smartlead API authentication failed (401): {response.text or 'Unauthorized'}. Please check your API key.")
 
67
  if attempt == max_retries - 1:
68
  raise Exception(f"Smartlead API error after {max_retries} attempts: {str(e)}")
69
  if response.status_code < 500:
 
10
 
11
  BASE_URL = "https://server.smartlead.ai/api/v1"
12
 
13
+ def __init__(self, api_key: Optional[str] = None, client_api_key: Optional[str] = None):
14
+ """
15
+ Initialize Smartlead client
16
+
17
+ Args:
18
+ api_key: Admin API key (required for campaign management operations)
19
+ client_api_key: Client API key (optional, may be required for certain operations)
20
+ """
21
  self.api_key = api_key or os.getenv("SMARTLEAD_API_KEY")
22
+ self.client_api_key = client_api_key or os.getenv("SMARTLEAD_CLIENT_API_KEY")
23
+
24
  if not self.api_key:
25
+ raise ValueError("SMARTLEAD_API_KEY environment variable is required (Admin API key)")
26
 
27
+ # Smartlead API uses query parameter authentication, not Bearer token
28
+ # According to docs: https://api.smartlead.ai/reference/authentication
29
  self.headers = {
 
30
  "Content-Type": "application/json"
31
  }
32
 
33
  def _make_request(self, method: str, endpoint: str, data: Optional[Dict] = None, max_retries: int = 3) -> Dict:
34
  """Make API request with retry logic for 429/5xx errors"""
35
+ # Smartlead API requires api_key as query parameter
36
+ # Format: ?api_key=yourApiKey
37
+ url = f"{self.BASE_URL}{endpoint}?api_key={self.api_key}"
38
+
39
+ # If client API key is provided, add it as well
40
+ if self.client_api_key:
41
+ url += f"&client_api_key={self.client_api_key}"
42
 
43
  for attempt in range(max_retries):
44
  try:
 
57
  error_msg = error_data.get('message') or error_data.get('error') or response.text or "Unauthorized"
58
  except:
59
  error_msg = response.text or "Unauthorized"
60
+ raise Exception(f"Smartlead API authentication failed (401): {error_msg}. Please verify your API key is correctly set in SMARTLEAD_API_KEY environment variable. If using client API key, also set SMARTLEAD_CLIENT_API_KEY.")
61
 
62
  # Handle rate limiting
63
  if response.status_code == 429:
 
77
 
78
  except requests.exceptions.HTTPError as e:
79
  if response.status_code == 401:
80
+ error_msg = response.text or 'Unauthorized'
81
+ raise Exception(f"Smartlead API authentication failed (401): {error_msg}. Please verify your API key is correctly set in SMARTLEAD_API_KEY environment variable.")
82
  if attempt == max_retries - 1:
83
  raise Exception(f"Smartlead API error after {max_retries} attempts: {str(e)}")
84
  if response.status_code < 500: