Skip to content

Commit e781250

Browse files
committed
feat: api keys async module
1 parent 5a1d2af commit e781250

3 files changed

Lines changed: 161 additions & 0 deletions

File tree

examples/api_keys_async.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import asyncio
2+
import os
3+
from typing import List
4+
5+
import resend
6+
7+
if not os.environ["RESEND_API_KEY"]:
8+
raise EnvironmentError("RESEND_API_KEY is missing")
9+
10+
# Set up async HTTP client
11+
resend.default_http_client = resend.HTTPXClient()
12+
13+
14+
async def main() -> None:
15+
create_params: resend.ApiKeys.CreateParams = {
16+
"name": "example.com",
17+
}
18+
19+
key: resend.ApiKey = await resend.ApiKeys.create_async(params=create_params)
20+
print("Created new api key")
21+
print(f"Key id: {key['id']} and token: {key['token']}")
22+
23+
keys: resend.ApiKeys.ListResponse = await resend.ApiKeys.list_async()
24+
for key in keys["data"]:
25+
print(key["id"])
26+
print(key["name"])
27+
print(key["created_at"])
28+
29+
if len(keys["data"]) > 0:
30+
await resend.ApiKeys.remove_async(api_key_id=keys["data"][0]["id"])
31+
print(f"Removed api key: {keys['data'][0]['id']}")
32+
33+
34+
if __name__ == "__main__":
35+
asyncio.run(main())

resend/api_keys/_api_keys.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
from resend import request
66
from resend.api_keys._api_key import ApiKey
77

8+
# Async imports (optional - only available with pip install resend[async])
9+
try:
10+
from resend.async_request import AsyncRequest
11+
except ImportError:
12+
pass
13+
814

915
class _ListResponse(TypedDict):
1016
data: List[ApiKey]
@@ -90,3 +96,54 @@ def remove(cls, api_key_id: str) -> None:
9096
# This would raise if failed
9197
request.Request[None](path=path, params={}, verb="delete").perform()
9298
return None
99+
100+
@classmethod
101+
async def create_async(cls, params: CreateParams) -> ApiKey:
102+
"""
103+
Add a new API key to authenticate communications with Resend (async).
104+
see more: https://resend.com/docs/api-reference/api-keys/create-api-key
105+
106+
Args:
107+
params (CreateParams): The API key creation parameters
108+
109+
Returns:
110+
ApiKey: The new API key object
111+
"""
112+
path = "/api-keys"
113+
resp = await AsyncRequest[ApiKey](
114+
path=path, params=cast(Dict[Any, Any], params), verb="post"
115+
).perform_with_content()
116+
return resp
117+
118+
@classmethod
119+
async def list_async(cls) -> ListResponse:
120+
"""
121+
Retrieve a list of API keys for the authenticated user (async).
122+
see more: https://resend.com/docs/api-reference/api-keys/list-api-keys
123+
124+
Returns:
125+
ListResponse: A list of API key objects
126+
"""
127+
path = "/api-keys"
128+
resp = await AsyncRequest[_ListResponse](
129+
path=path, params={}, verb="get"
130+
).perform_with_content()
131+
return resp
132+
133+
@classmethod
134+
async def remove_async(cls, api_key_id: str) -> None:
135+
"""
136+
Remove an existing API key (async).
137+
see more: https://resend.com/docs/api-reference/api-keys/delete-api-key
138+
139+
Args:
140+
api_key_id (str): The ID of the API key to remove
141+
142+
Returns:
143+
None
144+
"""
145+
path = f"/api-keys/{api_key_id}"
146+
147+
# This would raise if failed
148+
await AsyncRequest[None](path=path, params={}, verb="delete").perform()
149+
return None

tests/api_keys_async_test.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import pytest
2+
import resend
3+
from resend.exceptions import NoContentError
4+
from tests.conftest import ResendBaseTest
5+
6+
# flake8: noqa
7+
8+
9+
class TestResendApiKeysAsync(ResendBaseTest):
10+
@pytest.mark.asyncio
11+
async def test_api_keys_create_async(self) -> None:
12+
self.set_mock_json(
13+
{
14+
"id": "dacf4072-4119-4d88-932f-6202748ac7c8",
15+
"token": "re_c1tpEyD8_NKFusih9vKVQknRAQfmFcWCv",
16+
}
17+
)
18+
19+
params: resend.ApiKeys.CreateParams = {
20+
"name": "prod",
21+
}
22+
key: resend.ApiKey = await resend.ApiKeys.create_async(params)
23+
assert key["id"] == "dacf4072-4119-4d88-932f-6202748ac7c8"
24+
25+
@pytest.mark.asyncio
26+
async def test_should_create_api_key_async_raise_exception_when_no_content(self) -> None:
27+
self.set_mock_json(None)
28+
params: resend.ApiKeys.CreateParams = {
29+
"name": "prod",
30+
}
31+
with self.assertRaises(NoContentError):
32+
_ = await resend.ApiKeys.create_async(params)
33+
34+
@pytest.mark.asyncio
35+
async def test_api_keys_list_async(self) -> None:
36+
self.set_mock_json(
37+
{
38+
"data": [
39+
{
40+
"id": "91f3200a-df72-4654-b0cd-f202395f5354",
41+
"name": "Production",
42+
"created_at": "2023-04-08T00:11:13.110779+00:00",
43+
}
44+
]
45+
}
46+
)
47+
48+
keys: resend.ApiKeys.ListResponse = await resend.ApiKeys.list_async()
49+
for key in keys["data"]:
50+
assert key["id"] == "91f3200a-df72-4654-b0cd-f202395f5354"
51+
assert key["name"] == "Production"
52+
assert key["created_at"] == "2023-04-08T00:11:13.110779+00:00"
53+
54+
@pytest.mark.asyncio
55+
async def test_should_list_api_key_async_raise_exception_when_no_content(self) -> None:
56+
self.set_mock_json(None)
57+
with self.assertRaises(NoContentError):
58+
_ = await resend.ApiKeys.list_async()
59+
60+
@pytest.mark.asyncio
61+
async def test_api_keys_remove_async(self) -> None:
62+
self.set_mock_text("")
63+
64+
assert (
65+
await resend.ApiKeys.remove_async(
66+
api_key_id="4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
67+
)
68+
is None
69+
)

0 commit comments

Comments
 (0)