Skip to content

Commit e9bedf2

Browse files
authored
feat: adds ttl_seconds support (deepgram#557)
* feat: adds ttl_seconds support * resolves static check failures
1 parent eca4b1e commit e9bedf2

File tree

16 files changed

+414
-24
lines changed

16 files changed

+414
-24
lines changed

deepgram/clients/auth/v1/async_client.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# SPDX-License-Identifier: MIT
44

55
import logging
6+
from typing import Optional
67

78
from ....utils import verboselogs
89
from ....options import DeepgramClientOptions
@@ -28,23 +29,48 @@ def __init__(self, config: DeepgramClientOptions):
2829
self._endpoint = "v1/auth/grant"
2930
super().__init__(config)
3031

31-
async def grant_token(self):
32+
async def grant_token(self, ttl_seconds: Optional[int] = None):
3233
"""
33-
Generates a temporary JWT with a 30 second TTL.
34+
Generates a temporary JWT with a configurable TTL.
35+
36+
Args:
37+
ttl_seconds (int, optional): Time to live in seconds for the token.
38+
Must be between 1 and 3600 seconds. Defaults to 30 seconds.
3439
3540
Returns:
3641
GrantTokenResponse: An object containing the authentication token and its expiration time.
3742
3843
Raises:
3944
DeepgramTypeError: Raised for known API errors.
45+
ValueError: Raised when ttl_seconds is not within valid range.
4046
"""
4147
self._logger.debug("AuthRestClient.grant_token ENTER")
4248

49+
# Validate ttl_seconds if provided
50+
if ttl_seconds is not None:
51+
if not isinstance(ttl_seconds, int) or isinstance(ttl_seconds, bool) or ttl_seconds < 1 or ttl_seconds > 3600:
52+
raise ValueError("ttl_seconds must be an integer between 1 and 3600")
53+
4354
url = f"{self._config.url}/{self._endpoint}"
4455
self._logger.info("url: %s", url)
45-
result = await self.post(
46-
url, headers={"Authorization": f"Token {self._config.api_key}"}
47-
)
56+
57+
# Prepare request body
58+
request_body = {}
59+
if ttl_seconds is not None:
60+
request_body["ttl_seconds"] = ttl_seconds
61+
62+
# Make the request
63+
if request_body:
64+
result = await self.post(
65+
url,
66+
headers={"Authorization": f"Token {self._config.api_key}"},
67+
json=request_body
68+
)
69+
else:
70+
result = await self.post(
71+
url, headers={"Authorization": f"Token {self._config.api_key}"}
72+
)
73+
4874
self._logger.info("json: %s", result)
4975
res = GrantTokenResponse.from_json(result)
5076
self._logger.verbose("result: %s", res)

deepgram/clients/auth/v1/client.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# SPDX-License-Identifier: MIT
44

55
import logging
6+
from typing import Optional
67

78
from ....utils import verboselogs
89
from ....options import DeepgramClientOptions
@@ -28,23 +29,48 @@ def __init__(self, config: DeepgramClientOptions):
2829
self._endpoint = "v1/auth/grant"
2930
super().__init__(config)
3031

31-
def grant_token(self):
32+
def grant_token(self, ttl_seconds: Optional[int] = None):
3233
"""
33-
Generates a temporary JWT with a 30 second TTL.
34+
Generates a temporary JWT with a configurable TTL.
35+
36+
Args:
37+
ttl_seconds (int, optional): Time to live in seconds for the token.
38+
Must be between 1 and 3600 seconds. Defaults to 30 seconds.
3439
3540
Returns:
3641
GrantTokenResponse: An object containing the authentication token and its expiration time.
3742
3843
Raises:
3944
DeepgramTypeError: Raised for known API errors.
45+
ValueError: Raised when ttl_seconds is not within valid range.
4046
"""
4147
self._logger.debug("AuthRestClient.grant_token ENTER")
4248

49+
# Validate ttl_seconds if provided
50+
if ttl_seconds is not None:
51+
if not isinstance(ttl_seconds, int) or isinstance(ttl_seconds, bool) or ttl_seconds < 1 or ttl_seconds > 3600:
52+
raise ValueError("ttl_seconds must be an integer between 1 and 3600")
53+
4354
url = f"{self._config.url}/{self._endpoint}"
4455
self._logger.info("url: %s", url)
45-
result = self.post(
46-
url, headers={"Authorization": f"Token {self._config.api_key}"}
47-
)
56+
57+
# Prepare request body
58+
request_body = {}
59+
if ttl_seconds is not None:
60+
request_body["ttl_seconds"] = ttl_seconds
61+
62+
# Make the request
63+
if request_body:
64+
result = self.post(
65+
url,
66+
headers={"Authorization": f"Token {self._config.api_key}"},
67+
json=request_body
68+
)
69+
else:
70+
result = self.post(
71+
url, headers={"Authorization": f"Token {self._config.api_key}"}
72+
)
73+
4874
self._logger.info("json: %s", result)
4975
res = GrantTokenResponse.from_json(result)
5076
self._logger.verbose("result: %s", res)

examples/auth/async_token/main.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,25 @@ async def main():
2323
)
2424

2525
# STEP 2 Call the grant_token method on the auth rest class
26+
print("Testing async grant_token with default TTL (30 seconds)...")
2627
response = await deepgram.asyncauth.v("1").grant_token()
27-
print(f"response: {response}\n\n")
28+
print(f"Default TTL response: {response}\n")
29+
30+
# STEP 3 Call the grant_token method with custom TTL
31+
print("Testing async grant_token with custom TTL (300 seconds)...")
32+
response_custom = await deepgram.asyncauth.v("1").grant_token(ttl_seconds=300)
33+
print(f"Custom TTL response: {response_custom}\n")
34+
35+
# STEP 4 Test boundary values
36+
print("Testing async grant_token with minimum TTL (1 second)...")
37+
response_min = await deepgram.asyncauth.v("1").grant_token(ttl_seconds=1)
38+
print(f"Minimum TTL response: {response_min}\n")
39+
40+
print("Testing async grant_token with maximum TTL (3600 seconds)...")
41+
response_max = await deepgram.asyncauth.v("1").grant_token(ttl_seconds=3600)
42+
print(f"Maximum TTL response: {response_max}\n")
43+
44+
print("✅ All async grant_token tests completed successfully!")
2845
except Exception as e:
2946
print(f"Exception: {e}")
3047

examples/auth/bearer_token_demo/main.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ def main():
3030
f"API client created with auth: {api_client._config.headers.get('Authorization', 'Not set')}"
3131
)
3232

33-
# STEP 2 Use the API key client to get an access token
34-
print("\nStep 2: Getting access token...")
35-
response = api_client.auth.v("1").grant_token()
33+
# STEP 2 Use the API key client to get an access token with custom TTL
34+
print("\nStep 2: Getting access token with custom TTL (600 seconds)...")
35+
response = api_client.auth.v("1").grant_token(ttl_seconds=600)
3636
access_token = response.access_token
3737
print(f"Access token received: {access_token[:20]}...{access_token[-10:]}")
3838
print(f"Token expires in: {response.expires_in} seconds")

examples/auth/token/main.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,25 @@ def main():
2222
)
2323

2424
# STEP 2 Call the grant_token method on the auth rest class
25+
print("Testing grant_token with default TTL (30 seconds)...")
2526
response = deepgram.auth.v("1").grant_token()
26-
print(f"response: {response}\n\n")
27+
print(f"Default TTL response: {response}\n")
28+
29+
# STEP 3 Call the grant_token method with custom TTL
30+
print("Testing grant_token with custom TTL (300 seconds)...")
31+
response_custom = deepgram.auth.v("1").grant_token(ttl_seconds=300)
32+
print(f"Custom TTL response: {response_custom}\n")
33+
34+
# STEP 4 Test boundary values
35+
print("Testing grant_token with minimum TTL (1 second)...")
36+
response_min = deepgram.auth.v("1").grant_token(ttl_seconds=1)
37+
print(f"Minimum TTL response: {response_min}\n")
38+
39+
print("Testing grant_token with maximum TTL (3600 seconds)...")
40+
response_max = deepgram.auth.v("1").grant_token(ttl_seconds=3600)
41+
print(f"Maximum TTL response: {response_max}\n")
42+
43+
print("✅ All grant_token tests completed successfully!")
2744
except Exception as e:
2845
print(f"Exception: {e}")
2946

Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"metadata": {"transaction_key": "deprecated", "request_id": "ecae8f5b-ce66-40e3-b66c-41f6e2affe68", "sha256": "5324da68ede209a16ac69a38e8cd29cee4d754434a041166cda3a1f5e0b24566", "created": "2025-06-22T16:50:02.280Z", "duration": 17.566313, "channels": 1, "models": ["3b3aabe4-608a-46ac-9585-7960a25daf1a"], "model_info": {"3b3aabe4-608a-46ac-9585-7960a25daf1a": {"name": "general-nova-3", "version": "2024-12-20.0", "arch": "nova-3"}}, "summary_info": {"model_uuid": "67875a7f-c9c4-48a0-aa55-5bdb8a91c34a", "input_tokens": 0, "output_tokens": 0}}, "results": {"channels": [{"alternatives": [{"transcript": "Yep. I said it before, and I'll say it again. Life moves pretty fast. You don't stop and look around once in a while, you could miss it.", "confidence": 0.9991429, "words": [{"word": "yep", "start": 5.52, "end": 6.2400002, "confidence": 0.92345256, "punctuated_word": "Yep."}, {"word": "i", "start": 6.96, "end": 7.2799997, "confidence": 0.5776232, "punctuated_word": "I"}, {"word": "said", "start": 7.2799997, "end": 7.52, "confidence": 0.9052255, "punctuated_word": "said"}, {"word": "it", "start": 7.52, "end": 7.68, "confidence": 0.9979741, "punctuated_word": "it"}, {"word": "before", "start": 7.68, "end": 8.08, "confidence": 0.89339817, "punctuated_word": "before,"}, {"word": "and", "start": 8.08, "end": 8.16, "confidence": 0.99981827, "punctuated_word": "and"}, {"word": "i'll", "start": 8.16, "end": 8.4, "confidence": 0.99961734, "punctuated_word": "I'll"}, {"word": "say", "start": 8.4, "end": 8.48, "confidence": 0.99941754, "punctuated_word": "say"}, {"word": "it", "start": 8.48, "end": 8.639999, "confidence": 0.99959713, "punctuated_word": "it"}, {"word": "again", "start": 8.639999, "end": 8.96, "confidence": 0.95283747, "punctuated_word": "again."}, {"word": "life", "start": 10.071313, "end": 10.311313, "confidence": 0.9990012, "punctuated_word": "Life"}, {"word": "moves", "start": 10.311313, "end": 10.631312, "confidence": 0.9996643, "punctuated_word": "moves"}, {"word": "pretty", "start": 10.631312, "end": 11.031313, "confidence": 0.99988604, "punctuated_word": "pretty"}, {"word": "fast", "start": 11.031313, "end": 11.671312, "confidence": 0.99896836, "punctuated_word": "fast."}, {"word": "you", "start": 12.071312, "end": 12.311313, "confidence": 0.9201446, "punctuated_word": "You"}, {"word": "don't", "start": 12.311313, "end": 12.551312, "confidence": 0.99986017, "punctuated_word": "don't"}, {"word": "stop", "start": 12.551312, "end": 12.791312, "confidence": 0.99976414, "punctuated_word": "stop"}, {"word": "and", "start": 12.791312, "end": 12.951312, "confidence": 0.998522, "punctuated_word": "and"}, {"word": "look", "start": 12.951312, "end": 13.111313, "confidence": 0.9998677, "punctuated_word": "look"}, {"word": "around", "start": 13.111313, "end": 13.351313, "confidence": 0.9998548, "punctuated_word": "around"}, {"word": "once", "start": 13.351313, "end": 13.671312, "confidence": 0.9991429, "punctuated_word": "once"}, {"word": "in", "start": 13.671312, "end": 13.831312, "confidence": 0.9976286, "punctuated_word": "in"}, {"word": "a", "start": 13.831312, "end": 13.911312, "confidence": 0.9850873, "punctuated_word": "a"}, {"word": "while", "start": 13.911312, "end": 14.391312, "confidence": 0.9349425, "punctuated_word": "while,"}, {"word": "you", "start": 14.711312, "end": 14.871312, "confidence": 0.99921596, "punctuated_word": "you"}, {"word": "could", "start": 14.871312, "end": 15.031313, "confidence": 0.99974436, "punctuated_word": "could"}, {"word": "miss", "start": 15.031313, "end": 15.271313, "confidence": 0.9997111, "punctuated_word": "miss"}, {"word": "it", "start": 15.271313, "end": 15.5113125, "confidence": 0.9989148, "punctuated_word": "it."}], "paragraphs": {"transcript": "\nYep. I said it before, and I'll say it again. Life moves pretty fast. You don't stop and look around once in a while, you could miss it.", "paragraphs": [{"sentences": [{"text": "Yep.", "start": 5.52, "end": 6.2400002}, {"text": "I said it before, and I'll say it again.", "start": 6.96, "end": 8.96}, {"text": "Life moves pretty fast.", "start": 10.071313, "end": 11.671312}, {"text": "You don't stop and look around once in a while, you could miss it.", "start": 12.071312, "end": 15.5113125}], "start": 5.52, "end": 15.5113125, "num_words": 28}]}}]}], "summary": {"result": "success", "short": "Yep. I said it before, and I'll say it again. Life moves pretty fast. You don't stop and look around once in a while, you could miss it."}}}
1+
{"metadata": {"transaction_key": "deprecated", "request_id": "b8631296-99ec-4279-b619-875c9dc671b2", "sha256": "5324da68ede209a16ac69a38e8cd29cee4d754434a041166cda3a1f5e0b24566", "created": "2025-07-17T15:22:07.411Z", "duration": 17.566313, "channels": 1, "models": ["3b3aabe4-608a-46ac-9585-7960a25daf1a"], "model_info": {"3b3aabe4-608a-46ac-9585-7960a25daf1a": {"name": "general-nova-3", "version": "2024-12-20.0", "arch": "nova-3"}}, "summary_info": {"model_uuid": "67875a7f-c9c4-48a0-aa55-5bdb8a91c34a", "input_tokens": 0, "output_tokens": 0}}, "results": {"channels": [{"alternatives": [{"transcript": "Yep. I said it before, and I'll say it again. Life moves pretty fast. You don't stop and look around once in a while, you could miss it.", "confidence": 0.999143, "words": [{"word": "yep", "start": 5.52, "end": 6.2400002, "confidence": 0.92342806, "punctuated_word": "Yep."}, {"word": "i", "start": 6.96, "end": 7.2799997, "confidence": 0.57757515, "punctuated_word": "I"}, {"word": "said", "start": 7.2799997, "end": 7.52, "confidence": 0.9052356, "punctuated_word": "said"}, {"word": "it", "start": 7.52, "end": 7.68, "confidence": 0.99797314, "punctuated_word": "it"}, {"word": "before", "start": 7.68, "end": 8.08, "confidence": 0.8933872, "punctuated_word": "before,"}, {"word": "and", "start": 8.08, "end": 8.16, "confidence": 0.99981827, "punctuated_word": "and"}, {"word": "i'll", "start": 8.16, "end": 8.4, "confidence": 0.99961716, "punctuated_word": "I'll"}, {"word": "say", "start": 8.4, "end": 8.48, "confidence": 0.99941766, "punctuated_word": "say"}, {"word": "it", "start": 8.48, "end": 8.639999, "confidence": 0.999597, "punctuated_word": "it"}, {"word": "again", "start": 8.639999, "end": 8.96, "confidence": 0.9528253, "punctuated_word": "again."}, {"word": "life", "start": 10.071313, "end": 10.311313, "confidence": 0.9990013, "punctuated_word": "Life"}, {"word": "moves", "start": 10.311313, "end": 10.631312, "confidence": 0.9996643, "punctuated_word": "moves"}, {"word": "pretty", "start": 10.631312, "end": 11.031313, "confidence": 0.99988604, "punctuated_word": "pretty"}, {"word": "fast", "start": 11.031313, "end": 11.671312, "confidence": 0.9989686, "punctuated_word": "fast."}, {"word": "you", "start": 12.071312, "end": 12.311313, "confidence": 0.92013294, "punctuated_word": "You"}, {"word": "don't", "start": 12.311313, "end": 12.551312, "confidence": 0.99986017, "punctuated_word": "don't"}, {"word": "stop", "start": 12.551312, "end": 12.791312, "confidence": 0.99976414, "punctuated_word": "stop"}, {"word": "and", "start": 12.791312, "end": 12.951312, "confidence": 0.99852246, "punctuated_word": "and"}, {"word": "look", "start": 12.951312, "end": 13.111313, "confidence": 0.9998677, "punctuated_word": "look"}, {"word": "around", "start": 13.111313, "end": 13.351313, "confidence": 0.9998548, "punctuated_word": "around"}, {"word": "once", "start": 13.351313, "end": 13.671312, "confidence": 0.999143, "punctuated_word": "once"}, {"word": "in", "start": 13.671312, "end": 13.831312, "confidence": 0.9976291, "punctuated_word": "in"}, {"word": "a", "start": 13.831312, "end": 13.911312, "confidence": 0.98508644, "punctuated_word": "a"}, {"word": "while", "start": 13.911312, "end": 14.391312, "confidence": 0.9349461, "punctuated_word": "while,"}, {"word": "you", "start": 14.711312, "end": 14.871312, "confidence": 0.99921596, "punctuated_word": "you"}, {"word": "could", "start": 14.871312, "end": 15.031313, "confidence": 0.99974436, "punctuated_word": "could"}, {"word": "miss", "start": 15.031313, "end": 15.271313, "confidence": 0.9997112, "punctuated_word": "miss"}, {"word": "it", "start": 15.271313, "end": 15.5113125, "confidence": 0.99891484, "punctuated_word": "it."}], "paragraphs": {"transcript": "\nYep. I said it before, and I'll say it again. Life moves pretty fast. You don't stop and look around once in a while, you could miss it.", "paragraphs": [{"sentences": [{"text": "Yep.", "start": 5.52, "end": 6.2400002}, {"text": "I said it before, and I'll say it again.", "start": 6.96, "end": 8.96}, {"text": "Life moves pretty fast.", "start": 10.071313, "end": 11.671312}, {"text": "You don't stop and look around once in a while, you could miss it.", "start": 12.071312, "end": 15.5113125}], "start": 5.52, "end": 15.5113125, "num_words": 28}]}}]}], "summary": {"result": "success", "short": "Yep. I said it before, and I'll say it again. Life moves pretty fast. You don't stop and look around once in a while, you could miss it."}}}

0 commit comments

Comments
 (0)