Skip to content

Commit 1fda6bb

Browse files
authored
api key management (#42)
* api key management * fixes
1 parent 117445f commit 1fda6bb

File tree

2 files changed

+237
-0
lines changed

2 files changed

+237
-0
lines changed

api_keys.go

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
package openrouter
2+
3+
import (
4+
"context"
5+
"net/http"
6+
"path"
7+
"time"
8+
)
9+
10+
const (
11+
apiKeysSuffix = "/keys"
12+
apiKeySuffix = "/key"
13+
)
14+
15+
type KeyLimitReset string
16+
17+
const (
18+
KeyLimitResetDaily KeyLimitReset = "daily"
19+
KeyLimitResetWeekly KeyLimitReset = "weekly"
20+
KeyLimitResetMonthly KeyLimitReset = "monthly"
21+
)
22+
23+
type APIRateLimit struct {
24+
Requests int `json:"requests"`
25+
Interval string `json:"interval"`
26+
Note string `json:"note,omitempty"`
27+
}
28+
29+
type APIKey struct {
30+
Hash string `json:"hash,omitempty"`
31+
Name string `json:"name,omitempty"`
32+
Label string `json:"label,omitempty"`
33+
Disabled bool `json:"disabled,omitempty"`
34+
Limit float64 `json:"limit,omitempty"`
35+
LimitRemaining float64 `json:"limit_remaining,omitempty"`
36+
LimitReset KeyLimitReset `json:"limit_reset,omitempty"`
37+
IncludeByokInLimit bool `json:"include_byok_in_limit,omitempty"`
38+
39+
Usage float64 `json:"usage,omitempty"`
40+
UsageDaily float64 `json:"usage_daily,omitempty"`
41+
UsageWeekly float64 `json:"usage_weekly,omitempty"`
42+
UsageMonthly float64 `json:"usage_monthly,omitempty"`
43+
44+
ByokUsage float64 `json:"byok_usage,omitempty"`
45+
ByokUsageDaily float64 `json:"byok_usage_daily,omitempty"`
46+
ByokUsageWeekly float64 `json:"byok_usage_weekly,omitempty"`
47+
ByokUsageMonthly float64 `json:"byok_usage_monthly,omitempty"`
48+
49+
CreatedAt time.Time `json:"created_at,omitempty"`
50+
UpdatedAt *time.Time `json:"updated_at,omitempty"`
51+
ExpiresAt *time.Time `json:"expires_at,omitempty"`
52+
}
53+
54+
type APIKeyCurrent struct {
55+
Label string `json:"label,omitempty"`
56+
Limit float64 `json:"limit,omitempty"`
57+
Usage float64 `json:"usage,omitempty"`
58+
UsageDaily float64 `json:"usage_daily,omitempty"`
59+
UsageWeekly float64 `json:"usage_weekly,omitempty"`
60+
UsageMonthly float64 `json:"usage_monthly,omitempty"`
61+
ByokUsage float64 `json:"byok_usage,omitempty"`
62+
ByokUsageDaily float64 `json:"byok_usage_daily,omitempty"`
63+
ByokUsageWeekly float64 `json:"byok_usage_weekly,omitempty"`
64+
ByokUsageMonthly float64 `json:"byok_usage_monthly,omitempty"`
65+
IsFreeTier bool `json:"is_free_tier,omitempty"`
66+
IsProvisioningKey bool `json:"is_provisioning_key,omitempty"`
67+
LimitRemaining float64 `json:"limit_remaining,omitempty"`
68+
LimitReset KeyLimitReset `json:"limit_reset,omitempty"`
69+
IncludeByokInLimit bool `json:"include_byok_in_limit,omitempty"`
70+
RateLimit *APIRateLimit `json:"rate_limit,omitempty"`
71+
ExpiresAt *time.Time `json:"expires_at,omitempty"`
72+
}
73+
74+
type APIKeysListResponse struct {
75+
Data []APIKey `json:"data"`
76+
}
77+
78+
type APIKeyResponse struct {
79+
Data APIKey `json:"data"`
80+
}
81+
82+
type APIKeyCreateResponse struct {
83+
Data APIKey `json:"data"`
84+
Key string `json:"key,omitempty"`
85+
}
86+
87+
type APIKeyCurrentResponse struct {
88+
Data APIKeyCurrent `json:"data"`
89+
}
90+
91+
type APIKeyDeleteResponse struct {
92+
Deleted bool `json:"deleted"`
93+
}
94+
95+
type APIKeyCreateRequest struct {
96+
Name string `json:"name,omitempty"`
97+
Limit float64 `json:"limit,omitempty"`
98+
LimitReset KeyLimitReset `json:"limit_reset,omitempty"`
99+
IncludeByokInLimit *bool `json:"include_byok_in_limit,omitempty"`
100+
ExpiresAt *time.Time `json:"expires_at,omitempty"`
101+
}
102+
103+
type APIKeyUpdateRequest struct {
104+
Name *string `json:"name,omitempty"`
105+
Disabled *bool `json:"disabled,omitempty"`
106+
Limit *float64 `json:"limit,omitempty"`
107+
LimitReset *KeyLimitReset `json:"limit_reset,omitempty"`
108+
IncludeByokInLimit *bool `json:"include_byok_in_limit,omitempty"`
109+
ExpiresAt *time.Time `json:"expires_at,omitempty"`
110+
}
111+
112+
// ListAPIKeys lists all API keys for the current account.
113+
func (c *Client) ListAPIKeys(ctx context.Context) (APIKeysListResponse, error) {
114+
var res APIKeysListResponse
115+
116+
req, err := c.newRequest(
117+
ctx,
118+
http.MethodGet,
119+
c.fullURL(apiKeysSuffix),
120+
)
121+
if err != nil {
122+
return res, err
123+
}
124+
125+
err = c.sendRequest(req, &res)
126+
return res, err
127+
}
128+
129+
// CreateAPIKey creates a new API key.
130+
func (c *Client) CreateAPIKey(
131+
ctx context.Context,
132+
request APIKeyCreateRequest,
133+
) (APIKeyCreateResponse, error) {
134+
var res APIKeyCreateResponse
135+
136+
req, err := c.newRequest(
137+
ctx,
138+
http.MethodPost,
139+
c.fullURL(apiKeysSuffix),
140+
withBody(request),
141+
)
142+
if err != nil {
143+
return res, err
144+
}
145+
146+
err = c.sendRequest(req, &res)
147+
return res, err
148+
}
149+
150+
// GetAPIKey retrieves a single API key by hash.
151+
func (c *Client) GetAPIKey(ctx context.Context, hash string) (APIKeyResponse, error) {
152+
var res APIKeyResponse
153+
154+
req, err := c.newRequest(
155+
ctx,
156+
http.MethodGet,
157+
c.fullURL(path.Join(apiKeysSuffix, hash)),
158+
)
159+
if err != nil {
160+
return res, err
161+
}
162+
163+
err = c.sendRequest(req, &res)
164+
return res, err
165+
}
166+
167+
// DeleteAPIKey deletes a single API key by hash.
168+
func (c *Client) DeleteAPIKey(ctx context.Context, hash string) (APIKeyDeleteResponse, error) {
169+
var res APIKeyDeleteResponse
170+
171+
req, err := c.newRequest(
172+
ctx,
173+
http.MethodDelete,
174+
c.fullURL(path.Join(apiKeysSuffix, hash)),
175+
)
176+
if err != nil {
177+
return res, err
178+
}
179+
180+
err = c.sendRequest(req, &res)
181+
return res, err
182+
}
183+
184+
// UpdateAPIKey updates an API key by hash.
185+
func (c *Client) UpdateAPIKey(
186+
ctx context.Context,
187+
hash string,
188+
request APIKeyUpdateRequest,
189+
) (APIKeyResponse, error) {
190+
var res APIKeyResponse
191+
192+
req, err := c.newRequest(
193+
ctx,
194+
http.MethodPatch,
195+
c.fullURL(path.Join(apiKeysSuffix, hash)),
196+
withBody(request),
197+
)
198+
if err != nil {
199+
return res, err
200+
}
201+
202+
err = c.sendRequest(req, &res)
203+
return res, err
204+
}
205+
206+
// GetCurrentAPIKey returns information about the API key used for this request.
207+
func (c *Client) GetCurrentAPIKey(ctx context.Context) (APIKeyCurrentResponse, error) {
208+
var res APIKeyCurrentResponse
209+
210+
req, err := c.newRequest(
211+
ctx,
212+
http.MethodGet,
213+
c.fullURL(apiKeySuffix),
214+
)
215+
if err != nil {
216+
return res, err
217+
}
218+
219+
err = c.sendRequest(req, &res)
220+
return res, err
221+
}

client_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,3 +334,19 @@ func TestListEmbeddingsModels(t *testing.T) {
334334
require.NotEmpty(t, models)
335335
require.NotEmpty(t, models[0].ID)
336336
}
337+
338+
func TestGetCurrentAPIKey(t *testing.T) {
339+
client := createTestClient(t)
340+
341+
resp, err := client.GetCurrentAPIKey(context.Background())
342+
require.NoError(t, err)
343+
344+
require.NotNil(t, resp.Data.Label)
345+
require.NotEmpty(t, resp.Data.Label)
346+
347+
require.GreaterOrEqual(t, resp.Data.Usage, float64(0))
348+
349+
if resp.Data.RateLimit != nil {
350+
require.NotEmpty(t, resp.Data.RateLimit.Interval)
351+
}
352+
}

0 commit comments

Comments
 (0)