Skip to content

Commit 409466a

Browse files
authored
feat(api): v3 subscription api (#3696)
1 parent d2406bd commit 409466a

File tree

19 files changed

+2295
-138
lines changed

19 files changed

+2295
-138
lines changed

api/spec/src/v3/konnect.tsp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import "./events/index.tsp";
77
import "./meters/index.tsp";
88
import "./customers/index.tsp";
99
import "./entitlements/index.tsp";
10+
import "./subscriptions/index.tsp";
1011

1112
using TypeSpec.Http;
1213
using TypeSpec.OpenAPI;
@@ -30,6 +31,10 @@ using TypeSpec.OpenAPI;
3031
@tagMetadata(Shared.MetersTag, #{ description: Shared.MetersDescription })
3132
@tagMetadata(Shared.EventsTag, #{ description: Shared.EventsDescription })
3233
@tagMetadata(Shared.CustomersTag, #{ description: Shared.CustomersDescription })
34+
@tagMetadata(
35+
Shared.SubscriptionsTag,
36+
#{ description: Shared.SubscriptionsDescription }
37+
)
3338
@tagMetadata(
3439
Shared.EntitlementsTag,
3540
#{ description: Shared.EntitlementsDescription }
@@ -59,6 +64,12 @@ interface CustomersEndpoints extends Customers.CustomersOperations {}
5964
interface CustomerEntitlementsEndpoints
6065
extends Entitlements.CustomerEntitlementsOperations {}
6166

67+
@route("/openmeter/subscriptions")
68+
@tag(Shared.SubscriptionsTag)
69+
@friendlyName("${Shared.MeteringAndBillingTitle}: ${Shared.SubscriptionsTag}")
70+
interface SubscriptionsEndpoints
71+
extends Subscriptions.SubscriptionsOperations {}
72+
6273
/**
6374
* The system account access token is meant for automations and integrations that are not directly associated with a human identity.
6475
*/

api/spec/src/v3/openmeter.tsp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import "./shared/index.tsp";
66
import "./events/index.tsp";
77
import "./meters/index.tsp";
88
import "./customers/index.tsp";
9+
import "./subscriptions/index.tsp";
910

1011
using TypeSpec.Http;
1112
using TypeSpec.OpenAPI;
@@ -27,6 +28,10 @@ using TypeSpec.OpenAPI;
2728
@tagMetadata(Shared.MetersTag, #{ description: Shared.MetersDescription })
2829
@tagMetadata(Shared.EventsTag, #{ description: Shared.EventsDescription })
2930
@tagMetadata(Shared.CustomersTag, #{ description: Shared.CustomersDescription })
31+
@tagMetadata(
32+
Shared.SubscriptionsTag,
33+
#{ description: Shared.SubscriptionsDescription }
34+
)
3035
@tagMetadata(
3136
Shared.EntitlementsTag,
3237
#{ description: Shared.EntitlementsDescription }
@@ -54,3 +59,9 @@ interface CustomersEndpoints extends Customers.CustomersOperations {}
5459
@friendlyName("${Shared.OpenMeterTitle}: ${Shared.EntitlementsTag}")
5560
interface CustomerEntitlementsEndpoints
5661
extends Entitlements.CustomerEntitlementsOperations {}
62+
63+
@route("/openmeter/subscriptions")
64+
@tag(Shared.SubscriptionsTag)
65+
@friendlyName("${Shared.OpenMeterTitle}: ${Shared.SubscriptionsTag}")
66+
interface SubscriptionsEndpoints
67+
extends Subscriptions.SubscriptionsOperations {}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import "./subscription.tsp";
2+
import "./operations.tsp";
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import "@typespec/http";
2+
import "@typespec/openapi";
3+
import "@typespec/openapi3";
4+
import "../shared/index.tsp";
5+
import "../common/error.tsp";
6+
import "../common/pagination.tsp";
7+
import "../common/parameters.tsp";
8+
import "./subscription.tsp";
9+
10+
using TypeSpec.Http;
11+
using TypeSpec.OpenAPI;
12+
13+
namespace Subscriptions;
14+
15+
/**
16+
* Query params for listing subscriptions.
17+
*/
18+
@friendlyName("ListSubscriptionsParams")
19+
model ListSubscriptionsParams {
20+
...Common.PagePaginationQuery;
21+
22+
/**
23+
* Sort subscriptions returned in the response.
24+
* Supported sort attributes are:
25+
* - `id`
26+
* - `created_at`
27+
*
28+
* The `asc` suffix is optional as the default sort order is ascending.
29+
* The `desc` suffix is used to specify a descending order.
30+
*/
31+
@query(#{ name: "sort" })
32+
sort?: Common.SortQuery;
33+
34+
/**
35+
* Filter subscriptions.
36+
*/
37+
@query(#{ style: "deepObject", explode: true })
38+
filter?: {
39+
/**
40+
* Filter subscriptions by customer ID.
41+
*/
42+
customer_id?: Shared.ULID;
43+
};
44+
}
45+
46+
/**
47+
* Request for canceling a subscription.
48+
*/
49+
@friendlyName("BillingSubscriptionCancel")
50+
model SubscriptionCancel {
51+
/**
52+
* If not provided the subscription is canceled immediately.
53+
*/
54+
timing?: SubscriptionEditTiming = SubscriptionEditTimingEnum.immediate;
55+
}
56+
57+
/**
58+
* Request for changing a subscription.
59+
*/
60+
@friendlyName("BillingSubscriptionChange")
61+
model SubscriptionChange {
62+
...OmitProperties<SubscriptionCreate, "customer_id" | "customer_key">;
63+
64+
/**
65+
* Timing configuration for the change, when the change should take effect.
66+
* For changing a subscription, the accepted values depend on the subscription configuration.
67+
*/
68+
timing: SubscriptionEditTiming;
69+
}
70+
71+
/**
72+
* Response for changing a subscription.
73+
*/
74+
@friendlyName("BillingSubscriptionChangeResponse")
75+
model SubscriptionChangeResponse {
76+
/**
77+
* The current subscription before the change.
78+
*/
79+
current: Subscription;
80+
81+
/**
82+
* The new state of the subscription after the change.
83+
*/
84+
next: Subscription;
85+
}
86+
87+
interface SubscriptionsOperations {
88+
@post
89+
@operationId("create-subscription")
90+
@summary("Create subscription")
91+
@extension(Shared.UnstableExtension, true)
92+
@extension(Shared.InternalExtension, true)
93+
create(@body subscription: SubscriptionCreate):
94+
| Shared.CreateResponse<Subscription>
95+
| Common.NotFound
96+
| Common.Conflict
97+
| Common.ErrorResponses;
98+
99+
@get
100+
@operationId("list-subscriptions")
101+
@summary("List subscriptions")
102+
@extension(Shared.UnstableExtension, true)
103+
@extension(Shared.InternalExtension, true)
104+
list(
105+
...ListSubscriptionsParams,
106+
): Shared.PagePaginatedResponse<Subscription> | Common.NotFound | Common.ErrorResponses;
107+
108+
@get
109+
@operationId("get-subscription")
110+
@summary("Get subscription")
111+
@extension(Shared.UnstableExtension, true)
112+
@extension(Shared.InternalExtension, true)
113+
get(
114+
@path subscriptionId: Shared.ULID,
115+
): Shared.GetResponse<Subscription> | Common.NotFound | Common.ErrorResponses;
116+
117+
/**
118+
* Cancels the subscription.
119+
* Will result in a scheduling conflict if there are other subscriptions scheduled to start after the cancelation time.
120+
*/
121+
@post
122+
@operationId("cancel-subscription")
123+
@summary("Cancel subscription")
124+
@route("/cancel")
125+
@extension(Shared.UnstableExtension, true)
126+
@extension(Shared.InternalExtension, true)
127+
cancel(@path subscriptionId: Shared.ULID, @body body: SubscriptionCancel):
128+
| Shared.UpdateResponse<Subscription>
129+
| Common.NotFound
130+
| Common.Conflict
131+
| Common.ErrorResponses;
132+
133+
/**
134+
* Unschedules the subscription cancelation.
135+
*/
136+
@post
137+
@operationId("unschedule-cancelation")
138+
@summary("Unschedule subscription cancelation")
139+
@route("/unschedule-cancelation")
140+
@extension(Shared.UnstableExtension, true)
141+
@extension(Shared.InternalExtension, true)
142+
unscheduleCancelation(@path subscriptionId: Shared.ULID):
143+
| Shared.UpdateResponse<Subscription>
144+
| Common.NotFound
145+
| Common.Conflict
146+
| Common.ErrorResponses;
147+
148+
/**
149+
* Closes a running subscription and starts a new one according to the specification.
150+
* Can be used for upgrades, downgrades, and plan changes.
151+
*/
152+
@post
153+
@operationId("change-subscription")
154+
@summary("Change subscription")
155+
@extension(Shared.UnstableExtension, true)
156+
@extension(Shared.InternalExtension, true)
157+
@route("/change")
158+
change(
159+
@path subscriptionId: Shared.ULID,
160+
161+
@body
162+
body: SubscriptionChange,
163+
):
164+
| SubscriptionChangeResponse
165+
| Common.NotFound
166+
| Common.Conflict
167+
| Common.ErrorResponses;
168+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import "@typespec/openapi";
2+
import "../shared/index.tsp";
3+
4+
using TypeSpec.OpenAPI;
5+
6+
namespace Subscriptions;
7+
8+
/**
9+
* Subscription status.
10+
*/
11+
@friendlyName("BillingSubscriptionStatus")
12+
enum SubscriptionStatus {
13+
active,
14+
inactive,
15+
canceled,
16+
scheduled,
17+
}
18+
19+
/**
20+
* Subscription edit timing.
21+
* When immediate, the requested changes take effect immediately.
22+
* When next_billing_cycle, the requested changes take effect at the next billing cycle.
23+
*/
24+
@friendlyName("BillingSubscriptionEditTimingEnum")
25+
enum SubscriptionEditTimingEnum {
26+
immediate: "immediate",
27+
next_billing_cycle: "next_billing_cycle",
28+
}
29+
30+
/**
31+
* Subscription edit timing defined when the changes should take effect.
32+
* If the provided configuration is not supported by the subscription, an error will be returned.
33+
*/
34+
@oneOf
35+
@friendlyName("BillingSubscriptionEditTiming")
36+
union SubscriptionEditTiming {
37+
Enum: SubscriptionEditTimingEnum,
38+
Custom: DateTime,
39+
}
40+
41+
/**
42+
* Subscription create request.
43+
*/
44+
@friendlyName("BillingSubscriptionCreate")
45+
model SubscriptionCreate {
46+
...Shared.CreateRequest<OmitProperties<
47+
Subscription,
48+
"customer_id" | "plan_id" | "billing_anchor"
49+
>>;
50+
51+
/**
52+
* The ID of the customer to create the subscription for.
53+
*
54+
* Either customer ID or customer key must be provided.
55+
* If both are provided, the ID will be used.
56+
*/
57+
@visibility(Lifecycle.Create)
58+
@summary("Customer ID")
59+
customer_id?: Shared.ULID;
60+
61+
/**
62+
* The key of the customer to create the subscription for.
63+
*
64+
* Either customer ID or customer key must be provided.
65+
* If both are provided, the ID will be used.
66+
*/
67+
@visibility(Lifecycle.Create)
68+
@summary("Customer Key")
69+
customer_key?: Shared.ExternalResourceKey;
70+
71+
/**
72+
* The plan ID of the subscription.
73+
* Set if subscription is created from a plan.
74+
*
75+
* ID or Key of the plan is required if creating a subscription from a plan.
76+
* If both are provided, the ID will be used.
77+
*/
78+
@visibility(Lifecycle.Create)
79+
@summary("Plan ID")
80+
plan_id?: Shared.ULID;
81+
82+
/**
83+
* The plan Key of the subscription, if any.
84+
* Set if subscription is created from a plan.
85+
*
86+
* ID or Key of the plan is required if creating a subscription from a plan.
87+
* If both are provided, the ID will be used.
88+
*/
89+
@visibility(Lifecycle.Create)
90+
@summary("Plan Key")
91+
plan_key?: Shared.ResourceKey;
92+
93+
/**
94+
* The plan version of the subscription, if any.
95+
* If not provided, the latest version of the plan will be used.
96+
*/
97+
@visibility(Lifecycle.Create)
98+
@summary("Plan Version")
99+
plan_version?: integer;
100+
101+
/**
102+
* The billing anchor of the subscription.
103+
* Defaults to now if not provided.
104+
*/
105+
@visibility(Lifecycle.Create)
106+
@summary("Billing anchor")
107+
billing_anchor?: Shared.DateTime;
108+
}
109+
110+
/**
111+
* Subscription.
112+
*/
113+
@friendlyName("BillingSubscription")
114+
model Subscription {
115+
...OmitProperties<Shared.Resource, "name" | "description">;
116+
117+
/**
118+
* The customer ID of the subscription.
119+
*/
120+
@visibility(Lifecycle.Read)
121+
@summary("Customer ID")
122+
customer_id: Shared.ULID;
123+
124+
/**
125+
* The plan ID of the subscription.
126+
* Set if subscription is created from a plan.
127+
*/
128+
@visibility(Lifecycle.Read)
129+
@summary("Plan ID")
130+
plan_id?: Shared.ULID;
131+
132+
/**
133+
* The billing anchor of the subscription.
134+
*/
135+
@visibility(Lifecycle.Read)
136+
@summary("Billing anchor")
137+
billing_anchor: Shared.DateTime;
138+
139+
/**
140+
* The status of the subscription.
141+
*/
142+
@visibility(Lifecycle.Read)
143+
@summary("Status")
144+
status: SubscriptionStatus;
145+
}

0 commit comments

Comments
 (0)