whop-sdk 0.0.2__py3-none-any.whl → 0.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of whop-sdk might be problematic. Click here for more details.

Files changed (86) hide show
  1. whop_sdk/_client.py +47 -2
  2. whop_sdk/_version.py +1 -1
  3. whop_sdk/resources/__init__.py +70 -0
  4. whop_sdk/resources/checkout_configurations.py +4 -0
  5. whop_sdk/resources/course_chapters.py +602 -0
  6. whop_sdk/resources/course_lessons.py +722 -0
  7. whop_sdk/resources/courses.py +713 -0
  8. whop_sdk/resources/experiences.py +107 -0
  9. whop_sdk/resources/forum_posts.py +123 -1
  10. whop_sdk/resources/members.py +8 -0
  11. whop_sdk/resources/memberships.py +16 -8
  12. whop_sdk/resources/messages.py +113 -1
  13. whop_sdk/resources/payments.py +3 -26
  14. whop_sdk/resources/plans.py +74 -2
  15. whop_sdk/resources/products.py +8 -16
  16. whop_sdk/resources/promo_codes.py +652 -0
  17. whop_sdk/resources/reviews.py +315 -0
  18. whop_sdk/types/__init__.py +39 -0
  19. whop_sdk/types/assessment_question_types.py +7 -0
  20. whop_sdk/types/billing_reasons.py +9 -0
  21. whop_sdk/types/card_brands.py +24 -0
  22. whop_sdk/types/checkout_configuration_create_params.py +65 -2
  23. whop_sdk/types/checkout_configuration_list_response.py +4 -1
  24. whop_sdk/types/course.py +109 -0
  25. whop_sdk/types/course_chapter.py +32 -0
  26. whop_sdk/types/course_chapter_create_params.py +16 -0
  27. whop_sdk/types/course_chapter_delete_response.py +7 -0
  28. whop_sdk/types/course_chapter_list_params.py +25 -0
  29. whop_sdk/types/course_chapter_list_response.py +16 -0
  30. whop_sdk/types/course_chapter_update_params.py +12 -0
  31. whop_sdk/types/course_create_params.py +41 -0
  32. whop_sdk/types/course_delete_response.py +7 -0
  33. whop_sdk/types/course_lesson_create_params.py +27 -0
  34. whop_sdk/types/course_lesson_delete_response.py +7 -0
  35. whop_sdk/types/course_lesson_list_params.py +28 -0
  36. whop_sdk/types/course_lesson_list_response.py +35 -0
  37. whop_sdk/types/course_lesson_update_params.py +144 -0
  38. whop_sdk/types/course_list_params.py +28 -0
  39. whop_sdk/types/course_list_response.py +77 -0
  40. whop_sdk/types/course_update_params.py +89 -0
  41. whop_sdk/types/experience_duplicate_params.py +13 -0
  42. whop_sdk/types/forum_post_list_response.py +7 -0
  43. whop_sdk/types/forum_post_update_params.py +41 -0
  44. whop_sdk/types/languages.py +30 -0
  45. whop_sdk/types/ledger_account_retrieve_response.py +15 -1
  46. whop_sdk/types/lesson.py +159 -0
  47. whop_sdk/types/lesson_types.py +7 -0
  48. whop_sdk/types/lesson_visibilities.py +7 -0
  49. whop_sdk/types/member_list_params.py +3 -0
  50. whop_sdk/types/membership_list_params.py +7 -4
  51. whop_sdk/types/membership_list_response.py +12 -1
  52. whop_sdk/types/message_update_params.py +35 -0
  53. whop_sdk/types/payment_list_params.py +2 -7
  54. whop_sdk/types/payment_list_response.py +23 -13
  55. whop_sdk/types/payment_method_types.py +92 -0
  56. whop_sdk/types/plan_create_params.py +19 -1
  57. whop_sdk/types/plan_list_response.py +9 -0
  58. whop_sdk/types/plan_update_params.py +18 -0
  59. whop_sdk/types/product_create_params.py +1 -24
  60. whop_sdk/types/product_update_params.py +12 -1
  61. whop_sdk/types/promo_code.py +90 -0
  62. whop_sdk/types/promo_code_create_params.py +70 -0
  63. whop_sdk/types/promo_code_delete_response.py +7 -0
  64. whop_sdk/types/promo_code_list_params.py +37 -0
  65. whop_sdk/types/promo_code_list_response.py +79 -0
  66. whop_sdk/types/promo_code_status.py +7 -0
  67. whop_sdk/types/promo_duration.py +7 -0
  68. whop_sdk/types/review_list_params.py +31 -0
  69. whop_sdk/types/review_list_response.py +78 -0
  70. whop_sdk/types/review_retrieve_response.py +103 -0
  71. whop_sdk/types/review_status.py +7 -0
  72. whop_sdk/types/shared/checkout_configuration.py +4 -1
  73. whop_sdk/types/shared/forum_post.py +7 -0
  74. whop_sdk/types/shared/invoice.py +4 -1
  75. whop_sdk/types/shared/invoice_list_item.py +4 -1
  76. whop_sdk/types/shared/membership.py +12 -1
  77. whop_sdk/types/shared/payment.py +23 -13
  78. whop_sdk/types/shared/plan.py +9 -0
  79. whop_sdk/types/shared/product.py +8 -0
  80. whop_sdk/types/shared/product_list_item.py +8 -0
  81. whop_sdk/types/shared_params/__init__.py +1 -0
  82. whop_sdk/types/shared_params/promo_type.py +9 -0
  83. {whop_sdk-0.0.2.dist-info → whop_sdk-0.0.3.dist-info}/METADATA +1 -1
  84. {whop_sdk-0.0.2.dist-info → whop_sdk-0.0.3.dist-info}/RECORD +86 -41
  85. {whop_sdk-0.0.2.dist-info → whop_sdk-0.0.3.dist-info}/WHEEL +0 -0
  86. {whop_sdk-0.0.2.dist-info → whop_sdk-0.0.3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,89 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Iterable, Optional
6
+ from typing_extensions import Required, TypedDict
7
+
8
+ from .languages import Languages
9
+
10
+ __all__ = ["CourseUpdateParams", "Chapter", "ChapterLesson", "Thumbnail"]
11
+
12
+
13
+ class CourseUpdateParams(TypedDict, total=False):
14
+ certificate_after_completion_enabled: Optional[bool]
15
+ """
16
+ Whether the course will award its students a PDF certificate after completing
17
+ all lessons
18
+ """
19
+
20
+ chapters: Optional[Iterable[Chapter]]
21
+ """The chapters and lessons to update"""
22
+
23
+ cover_image: Optional[str]
24
+ """The cover image URL of the course"""
25
+
26
+ description: Optional[str]
27
+ """A short description of the course"""
28
+
29
+ language: Optional[Languages]
30
+ """The available languages for a course"""
31
+
32
+ require_completing_lessons_in_order: Optional[bool]
33
+ """
34
+ Whether the course requires students to complete the previous lesson before
35
+ moving on to the next one
36
+ """
37
+
38
+ tagline: Optional[str]
39
+ """A short tagline for the course"""
40
+
41
+ thumbnail: Optional[Thumbnail]
42
+ """The thumbnail for the course in png, jpeg, or gif format"""
43
+
44
+ title: Optional[str]
45
+ """The title of the course"""
46
+
47
+
48
+ class ChapterLesson(TypedDict, total=False):
49
+ id: Required[str]
50
+ """The ID of the lesson to update"""
51
+
52
+ chapter_id: Required[str]
53
+ """The ID of the chapter this lesson belongs to (for moving between chapters)"""
54
+
55
+ order: Required[int]
56
+ """The order of the lesson within its chapter"""
57
+
58
+ title: Required[str]
59
+ """The title of the lesson"""
60
+
61
+
62
+ class Chapter(TypedDict, total=False):
63
+ id: Required[str]
64
+ """The ID of the chapter to update"""
65
+
66
+ order: Required[int]
67
+ """The order of the chapter within its course"""
68
+
69
+ title: Required[str]
70
+ """The title of the chapter"""
71
+
72
+ lessons: Optional[Iterable[ChapterLesson]]
73
+ """The lessons to update within this chapter"""
74
+
75
+
76
+ class Thumbnail(TypedDict, total=False):
77
+ id: Optional[str]
78
+ """The ID of an existing attachment object.
79
+
80
+ Use this when updating a resource and keeping a subset of the attachments. Don't
81
+ use this unless you know what you're doing.
82
+ """
83
+
84
+ direct_upload_id: Optional[str]
85
+ """This ID should be used the first time you upload an attachment.
86
+
87
+ It is the ID of the direct upload that was created when uploading the file to S3
88
+ via the mediaDirectUpload mutation.
89
+ """
@@ -0,0 +1,13 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Optional
6
+ from typing_extensions import TypedDict
7
+
8
+ __all__ = ["ExperienceDuplicateParams"]
9
+
10
+
11
+ class ExperienceDuplicateParams(TypedDict, total=False):
12
+ name: Optional[str]
13
+ """The name of the new experience"""
@@ -1,6 +1,7 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  from typing import Optional
4
+ from datetime import datetime
4
5
 
5
6
  from .._models import BaseModel
6
7
 
@@ -28,6 +29,9 @@ class ForumPostListResponse(BaseModel):
28
29
  content: Optional[str] = None
29
30
  """The content of the forum post in Markdown format"""
30
31
 
32
+ created_at: datetime
33
+ """The timestamp when the post was created"""
34
+
31
35
  is_edited: bool
32
36
  """Whether the forum post has been edited"""
33
37
 
@@ -46,6 +50,9 @@ class ForumPostListResponse(BaseModel):
46
50
  title: Optional[str] = None
47
51
  """The title of the forum post"""
48
52
 
53
+ updated_at: datetime
54
+ """The timestamp when the post was last updated"""
55
+
49
56
  user: User
50
57
  """The user who created this forum post"""
51
58
 
@@ -0,0 +1,41 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Iterable, Optional
6
+ from typing_extensions import TypedDict
7
+
8
+ __all__ = ["ForumPostUpdateParams", "Attachment"]
9
+
10
+
11
+ class ForumPostUpdateParams(TypedDict, total=False):
12
+ attachments: Optional[Iterable[Attachment]]
13
+ """The attachments for this post"""
14
+
15
+ content: Optional[str]
16
+ """This is the main body of the post in Markdown format.
17
+
18
+ Hidden if paywalled and user hasn't purchased access to it.
19
+ """
20
+
21
+ is_pinned: Optional[bool]
22
+ """Whether the post is pinned. You can only pin a top level posts (not comments)."""
23
+
24
+ title: Optional[str]
25
+ """The title of the post. Only visible if paywalled."""
26
+
27
+
28
+ class Attachment(TypedDict, total=False):
29
+ id: Optional[str]
30
+ """The ID of an existing attachment object.
31
+
32
+ Use this when updating a resource and keeping a subset of the attachments. Don't
33
+ use this unless you know what you're doing.
34
+ """
35
+
36
+ direct_upload_id: Optional[str]
37
+ """This ID should be used the first time you upload an attachment.
38
+
39
+ It is the ID of the direct upload that was created when uploading the file to S3
40
+ via the mediaDirectUpload mutation.
41
+ """
@@ -0,0 +1,30 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from typing_extensions import Literal, TypeAlias
4
+
5
+ __all__ = ["Languages"]
6
+
7
+ Languages: TypeAlias = Literal[
8
+ "en",
9
+ "es",
10
+ "it",
11
+ "pt",
12
+ "de",
13
+ "fr",
14
+ "pl",
15
+ "ru",
16
+ "nl",
17
+ "ca",
18
+ "tr",
19
+ "sv",
20
+ "uk",
21
+ "no",
22
+ "fi",
23
+ "sk",
24
+ "el",
25
+ "cs",
26
+ "hr",
27
+ "da",
28
+ "ro",
29
+ "bg",
30
+ ]
@@ -62,7 +62,21 @@ class LedgerAccountRetrieveResponse(BaseModel):
62
62
  balances: List[Balance]
63
63
  """The balances associated with the account."""
64
64
 
65
- ledger_account_audit_status: Optional[Literal["reserves_imposed", "requested_more_information"]] = None
65
+ ledger_account_audit_status: Optional[
66
+ Literal[
67
+ "pending",
68
+ "approved",
69
+ "reserves_imposed",
70
+ "suspended",
71
+ "ignored",
72
+ "rejected",
73
+ "requested_more_information",
74
+ "information_submitted",
75
+ "requested_tos_violation_correction",
76
+ "clawback_attempted",
77
+ "awaiting_sales_review",
78
+ ]
79
+ ] = None
66
80
  """The different statuses a LedgerAccountAudit can be"""
67
81
 
68
82
  ledger_type: Literal["primary", "pool"]
@@ -0,0 +1,159 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from typing import List, Optional
4
+ from datetime import datetime
5
+
6
+ from .._models import BaseModel
7
+ from .lesson_types import LessonTypes
8
+ from .lesson_visibilities import LessonVisibilities
9
+ from .assessment_question_types import AssessmentQuestionTypes
10
+
11
+ __all__ = [
12
+ "Lesson",
13
+ "AssessmentQuestion",
14
+ "AssessmentQuestionImage",
15
+ "AssessmentQuestionOption",
16
+ "Attachment",
17
+ "MainPdf",
18
+ "VideoAsset",
19
+ ]
20
+
21
+
22
+ class AssessmentQuestionImage(BaseModel):
23
+ id: str
24
+ """The ID of the attachment"""
25
+
26
+ content_type: Optional[str] = None
27
+ """The attachment's content type (e.g., image/jpg, video/mp4)"""
28
+
29
+ filename: Optional[str] = None
30
+ """The name of the file"""
31
+
32
+ url: Optional[str] = None
33
+ """This is the URL you use to render optimized attachments on the client.
34
+
35
+ This should be used for apps.
36
+ """
37
+
38
+
39
+ class AssessmentQuestionOption(BaseModel):
40
+ id: str
41
+ """The ID of the assessment question option"""
42
+
43
+ is_correct: bool
44
+ """Whether this option is a correct answer"""
45
+
46
+ option_text: str
47
+ """The text of the answer option"""
48
+
49
+ order: int
50
+ """The order of this option within the question"""
51
+
52
+
53
+ class AssessmentQuestion(BaseModel):
54
+ id: str
55
+ """The ID of the assessment question"""
56
+
57
+ correct_answer: str
58
+ """The correct answer for the question. Used for short answer questions"""
59
+
60
+ created_at: datetime
61
+ """When the question was created"""
62
+
63
+ image: Optional[AssessmentQuestionImage] = None
64
+ """Optional image attachment for the question"""
65
+
66
+ options: List[AssessmentQuestionOption]
67
+ """The answer options for multiple choice/select questions"""
68
+
69
+ order: int
70
+ """The order of the question within its lesson"""
71
+
72
+ question_text: str
73
+ """The text of the question"""
74
+
75
+ question_type: AssessmentQuestionTypes
76
+ """The type of the question"""
77
+
78
+
79
+ class Attachment(BaseModel):
80
+ id: str
81
+ """The ID of the attachment"""
82
+
83
+ content_type: Optional[str] = None
84
+ """The attachment's content type (e.g., image/jpg, video/mp4)"""
85
+
86
+ filename: Optional[str] = None
87
+ """The name of the file"""
88
+
89
+ url: Optional[str] = None
90
+ """This is the URL you use to render optimized attachments on the client.
91
+
92
+ This should be used for apps.
93
+ """
94
+
95
+
96
+ class MainPdf(BaseModel):
97
+ id: str
98
+ """The ID of the attachment"""
99
+
100
+ content_type: Optional[str] = None
101
+ """The attachment's content type (e.g., image/jpg, video/mp4)"""
102
+
103
+ filename: Optional[str] = None
104
+ """The name of the file"""
105
+
106
+ url: Optional[str] = None
107
+ """This is the URL you use to render optimized attachments on the client.
108
+
109
+ This should be used for apps.
110
+ """
111
+
112
+
113
+ class VideoAsset(BaseModel):
114
+ id: str
115
+ """The ID of the Mux asset"""
116
+
117
+ asset_id: Optional[str] = None
118
+ """The Mux-provided ID of the asset"""
119
+
120
+ playback_id: Optional[str] = None
121
+ """The public playback ID of the Mux asset"""
122
+
123
+
124
+ class Lesson(BaseModel):
125
+ id: str
126
+ """The ID of the lesson"""
127
+
128
+ assessment_questions: List[AssessmentQuestion]
129
+ """Assessment questions for quiz/knowledge check lessons"""
130
+
131
+ attachments: List[Attachment]
132
+ """The attached files in this lesson as a flat array"""
133
+
134
+ content: Optional[str] = None
135
+ """The content of the lesson"""
136
+
137
+ days_from_course_start_until_unlock: Optional[int] = None
138
+ """Number of days from course start until the lesson is unlocked"""
139
+
140
+ lesson_type: LessonTypes
141
+ """The type of the lesson (text, video, pdf, multi, quiz, knowledge_check)"""
142
+
143
+ main_pdf: Optional[MainPdf] = None
144
+ """The main PDF file for this lesson"""
145
+
146
+ order: int
147
+ """The order of the lesson within its chapter"""
148
+
149
+ title: str
150
+ """The title of the lesson"""
151
+
152
+ video_asset: Optional[VideoAsset] = None
153
+ """The associated Mux asset for video lessons"""
154
+
155
+ visibility: LessonVisibilities
156
+ """The visibility of the lesson.
157
+
158
+ Determines how / whether this lesson is visible to users.
159
+ """
@@ -0,0 +1,7 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from typing_extensions import Literal, TypeAlias
4
+
5
+ __all__ = ["LessonTypes"]
6
+
7
+ LessonTypes: TypeAlias = Literal["text", "video", "pdf", "multi", "quiz", "knowledge_check"]
@@ -0,0 +1,7 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from typing_extensions import Literal, TypeAlias
4
+
5
+ __all__ = ["LessonVisibilities"]
6
+
7
+ LessonVisibilities: TypeAlias = Literal["visible", "hidden"]
@@ -68,3 +68,6 @@ class MemberListParams(TypedDict, total=False):
68
68
 
69
69
  statuses: Optional[List[MemberStatuses]]
70
70
  """The statuses to filter the members by"""
71
+
72
+ user_ids: Optional[SequenceNotStr[str]]
73
+ """The user IDs to filter the members by"""
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  from typing import List, Union, Optional
6
6
  from datetime import datetime
7
- from typing_extensions import Literal, Required, Annotated, TypedDict
7
+ from typing_extensions import Literal, Annotated, TypedDict
8
8
 
9
9
  from .._types import SequenceNotStr
10
10
  from .._utils import PropertyInfo
@@ -15,9 +15,6 @@ __all__ = ["MembershipListParams"]
15
15
 
16
16
 
17
17
  class MembershipListParams(TypedDict, total=False):
18
- company_id: Required[str]
19
- """The ID of the company to list memberships for"""
20
-
21
18
  access_pass_ids: Optional[SequenceNotStr[str]]
22
19
  """The access pass IDs to filter the memberships by"""
23
20
 
@@ -42,6 +39,9 @@ class MembershipListParams(TypedDict, total=False):
42
39
  ]
43
40
  """The cancel options to filter the memberships by"""
44
41
 
42
+ company_id: Optional[str]
43
+ """The ID of the company to list memberships for"""
44
+
45
45
  created_after: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
46
46
  """The minimum creation date to filter by"""
47
47
 
@@ -68,3 +68,6 @@ class MembershipListParams(TypedDict, total=False):
68
68
 
69
69
  statuses: Optional[List[MembershipStatus]]
70
70
  """The membership status to filter the memberships by"""
71
+
72
+ user_ids: Optional[SequenceNotStr[str]]
73
+ """Only return memberships from these whop user ids"""
@@ -7,7 +7,7 @@ from .._models import BaseModel
7
7
  from .shared.currency import Currency
8
8
  from .shared.membership_status import MembershipStatus
9
9
 
10
- __all__ = ["MembershipListResponse", "Company", "Member", "Plan", "PromoCode", "User"]
10
+ __all__ = ["MembershipListResponse", "Company", "Member", "Plan", "Product", "PromoCode", "User"]
11
11
 
12
12
 
13
13
  class Company(BaseModel):
@@ -28,6 +28,14 @@ class Plan(BaseModel):
28
28
  """The internal ID of the plan."""
29
29
 
30
30
 
31
+ class Product(BaseModel):
32
+ id: str
33
+ """The internal ID of the public product."""
34
+
35
+ title: str
36
+ """The title of the product. Use for Whop 4.0."""
37
+
38
+
31
39
  class PromoCode(BaseModel):
32
40
  id: str
33
41
  """The ID of the promo."""
@@ -92,6 +100,9 @@ class MembershipListResponse(BaseModel):
92
100
  plan: Plan
93
101
  """The Plan this Membership is for."""
94
102
 
103
+ product: Product
104
+ """The Product this Membership grants access to."""
105
+
95
106
  promo_code: Optional[PromoCode] = None
96
107
  """The Promo Code that is currently applied to this Membership."""
97
108
 
@@ -0,0 +1,35 @@
1
+ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Iterable, Optional
6
+ from typing_extensions import TypedDict
7
+
8
+ __all__ = ["MessageUpdateParams", "Attachment"]
9
+
10
+
11
+ class MessageUpdateParams(TypedDict, total=False):
12
+ attachments: Optional[Iterable[Attachment]]
13
+ """The attachments for this message"""
14
+
15
+ content: Optional[str]
16
+ """The content of the message in Markdown format"""
17
+
18
+ is_pinned: Optional[bool]
19
+ """Whether this message is pinned"""
20
+
21
+
22
+ class Attachment(TypedDict, total=False):
23
+ id: Optional[str]
24
+ """The ID of an existing attachment object.
25
+
26
+ Use this when updating a resource and keeping a subset of the attachments. Don't
27
+ use this unless you know what you're doing.
28
+ """
29
+
30
+ direct_upload_id: Optional[str]
31
+ """This ID should be used the first time you upload an attachment.
32
+
33
+ It is the ID of the direct upload that was created when uploading the file to S3
34
+ via the mediaDirectUpload mutation.
35
+ """
@@ -8,6 +8,7 @@ from typing_extensions import Literal, Required, Annotated, TypedDict
8
8
 
9
9
  from .._types import SequenceNotStr
10
10
  from .._utils import PropertyInfo
11
+ from .billing_reasons import BillingReasons
11
12
  from .shared.currency import Currency
12
13
  from .shared.direction import Direction
13
14
  from .shared.receipt_status import ReceiptStatus
@@ -26,13 +27,7 @@ class PaymentListParams(TypedDict, total=False):
26
27
  before: Optional[str]
27
28
  """Returns the elements in the list that come before the specified cursor."""
28
29
 
29
- billing_reasons: Optional[
30
- List[
31
- Literal[
32
- "subscription_create", "subscription_cycle", "subscription_update", "one_time", "manual", "subscription"
33
- ]
34
- ]
35
- ]
30
+ billing_reasons: Optional[List[BillingReasons]]
36
31
  """The billing reason for the payment"""
37
32
 
38
33
  created_after: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
@@ -4,8 +4,11 @@ from typing import Optional
4
4
  from datetime import datetime
5
5
 
6
6
  from .._models import BaseModel
7
+ from .card_brands import CardBrands
8
+ from .billing_reasons import BillingReasons
7
9
  from .shared.currency import Currency
8
10
  from .shared.promo_type import PromoType
11
+ from .payment_method_types import PaymentMethodTypes
9
12
  from .shared.receipt_status import ReceiptStatus
10
13
  from .shared.membership_status import MembershipStatus
11
14
  from .shared.friendly_receipt_status import FriendlyReceiptStatus
@@ -103,7 +106,7 @@ class PromoCode(BaseModel):
103
106
  """The specific code used to apply the promo at checkout."""
104
107
 
105
108
  number_of_intervals: Optional[int] = None
106
- """The number of billing cycles the promo is applied for."""
109
+ """The number of months the promo is applied for."""
107
110
 
108
111
  promo_type: PromoType
109
112
  """The type (% or flat amount) of the promo."""
@@ -136,11 +139,11 @@ class PaymentListResponse(BaseModel):
136
139
  billing_address: Optional[BillingAddress] = None
137
140
  """The address of the user who made the payment."""
138
141
 
139
- billing_reason: Optional[str] = None
140
- """The billing reason"""
142
+ billing_reason: Optional[BillingReasons] = None
143
+ """The reason why a specific payment was billed"""
141
144
 
142
- card_brand: Optional[str] = None
143
- """The type of card used as the payment method."""
145
+ card_brand: Optional[CardBrands] = None
146
+ """Possible card brands that a payment token can have"""
144
147
 
145
148
  card_last4: Optional[str] = None
146
149
  """The last 4 digits of the card used to make the payment."""
@@ -172,11 +175,8 @@ class PaymentListResponse(BaseModel):
172
175
  paid_at: Optional[datetime] = None
173
176
  """The datetime the payment was paid"""
174
177
 
175
- payment_method_type: Optional[str] = None
176
- """Returns the type of payment method used for the payment, if available.
177
-
178
- Ex. klarna, affirm, card, cashapp
179
- """
178
+ payment_method_type: Optional[PaymentMethodTypes] = None
179
+ """The different types of payment methods that can be used."""
180
180
 
181
181
  plan: Optional[Plan] = None
182
182
  """The plan attached to this payment."""
@@ -188,7 +188,10 @@ class PaymentListResponse(BaseModel):
188
188
  """The promo code used for this payment."""
189
189
 
190
190
  refundable: bool
191
- """Whether the payment can be refunded."""
191
+ """
192
+ True only for payments that are `paid`, have not been fully refunded, and were
193
+ processed by a payment processor that allows refunds.
194
+ """
192
195
 
193
196
  refunded_amount: Optional[float] = None
194
197
  """The payment refund amount(if applicable)."""
@@ -197,7 +200,11 @@ class PaymentListResponse(BaseModel):
197
200
  """When the payment was refunded (if applicable)."""
198
201
 
199
202
  retryable: bool
200
- """Whether the payment can be retried."""
203
+ """
204
+ True when the payment status is `open` and its membership is in one of the
205
+ retry-eligible states (`active`, `trialing`, `completed`, or `past_due`);
206
+ otherwise false. Used to decide if Whop can attempt the charge again.
207
+ """
201
208
 
202
209
  status: Optional[ReceiptStatus] = None
203
210
  """The status of a receipt"""
@@ -218,4 +225,7 @@ class PaymentListResponse(BaseModel):
218
225
  """The user that made this payment."""
219
226
 
220
227
  voidable: bool
221
- """Whether the payment can be voided."""
228
+ """
229
+ True when the payment is tied to a membership in `past_due`, the payment status
230
+ is `open`, and the processor allows voiding payments; otherwise false.
231
+ """