polar-ruby 0.1.0

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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/CHANGELOG.md +50 -0
  4. data/DEVELOPMENT.md +329 -0
  5. data/EXAMPLES.md +385 -0
  6. data/Gemfile +12 -0
  7. data/Gemfile.lock +115 -0
  8. data/LICENSE +23 -0
  9. data/PROJECT_SUMMARY.md +256 -0
  10. data/README.md +635 -0
  11. data/Rakefile +24 -0
  12. data/examples/demo.rb +106 -0
  13. data/lib/polar/authentication.rb +83 -0
  14. data/lib/polar/client.rb +144 -0
  15. data/lib/polar/configuration.rb +46 -0
  16. data/lib/polar/customer_portal/benefit_grants.rb +41 -0
  17. data/lib/polar/customer_portal/customers.rb +69 -0
  18. data/lib/polar/customer_portal/license_keys.rb +70 -0
  19. data/lib/polar/customer_portal/orders.rb +82 -0
  20. data/lib/polar/customer_portal/subscriptions.rb +51 -0
  21. data/lib/polar/errors.rb +96 -0
  22. data/lib/polar/http_client.rb +150 -0
  23. data/lib/polar/pagination.rb +133 -0
  24. data/lib/polar/resources/base.rb +47 -0
  25. data/lib/polar/resources/benefits.rb +64 -0
  26. data/lib/polar/resources/checkouts.rb +75 -0
  27. data/lib/polar/resources/customers.rb +120 -0
  28. data/lib/polar/resources/events.rb +45 -0
  29. data/lib/polar/resources/files.rb +57 -0
  30. data/lib/polar/resources/license_keys.rb +81 -0
  31. data/lib/polar/resources/metrics.rb +30 -0
  32. data/lib/polar/resources/oauth2.rb +61 -0
  33. data/lib/polar/resources/orders.rb +54 -0
  34. data/lib/polar/resources/organizations.rb +41 -0
  35. data/lib/polar/resources/payments.rb +29 -0
  36. data/lib/polar/resources/products.rb +58 -0
  37. data/lib/polar/resources/subscriptions.rb +55 -0
  38. data/lib/polar/resources/webhooks.rb +81 -0
  39. data/lib/polar/version.rb +5 -0
  40. data/lib/polar/webhooks.rb +174 -0
  41. data/lib/polar.rb +65 -0
  42. metadata +239 -0
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Polar
6
+ module Resources
7
+ class Events < Base
8
+ # List events
9
+ # @param params [Hash] Query parameters
10
+ # @option params [String] :organization_id Filter by organization ID
11
+ # @option params [String] :type Filter by event type
12
+ # @option params [Integer] :page Page number
13
+ # @option params [Integer] :limit Items per page
14
+ # @return [PaginatedResponse] Paginated list of events
15
+ def list(params = {})
16
+ paginate('/events/', params)
17
+ end
18
+
19
+ # List event names
20
+ # @param params [Hash] Query parameters
21
+ # @return [Array] List of available event names
22
+ def list_names(params = {})
23
+ response = get('/events/names', params)
24
+ response.body
25
+ end
26
+
27
+ # Get an event by ID
28
+ # @param id [String] Event ID
29
+ # @return [Hash] Event data
30
+ def get(id)
31
+ response = get("/events/#{id}")
32
+ response.body
33
+ end
34
+
35
+ # Ingest events
36
+ # @param events [Array] Array of event data
37
+ # @return [Hash] Ingestion result
38
+ def ingest(events)
39
+ body = { events: events }
40
+ response = post('/events/', body)
41
+ response.body
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Polar
6
+ module Resources
7
+ class Files < Base
8
+ # List files
9
+ # @param params [Hash] Query parameters
10
+ # @option params [String] :organization_id Filter by organization ID
11
+ # @option params [Integer] :page Page number
12
+ # @option params [Integer] :limit Items per page
13
+ # @return [PaginatedResponse] Paginated list of files
14
+ def list(params = {})
15
+ paginate('/files/', params)
16
+ end
17
+
18
+ # Create a file upload
19
+ # @param attributes [Hash] File attributes
20
+ # @option attributes [String] :name File name
21
+ # @option attributes [String] :mime_type File MIME type
22
+ # @option attributes [Integer] :size File size in bytes
23
+ # @option attributes [String] :organization_id Organization ID
24
+ # @return [Hash] File upload information including signed URL
25
+ def create(attributes)
26
+ response = post('/files/', attributes)
27
+ response.body
28
+ end
29
+
30
+ # Mark file upload as completed
31
+ # @param id [String] File ID
32
+ # @param completion_data [Hash] Upload completion data
33
+ # @return [Hash] Completed file data
34
+ def uploaded(id, completion_data = {})
35
+ response = post("/files/#{id}/uploaded", completion_data)
36
+ response.body
37
+ end
38
+
39
+ # Update file metadata
40
+ # @param id [String] File ID
41
+ # @param attributes [Hash] Updated attributes
42
+ # @return [Hash] Updated file
43
+ def update(id, attributes)
44
+ response = patch("/files/#{id}", attributes)
45
+ response.body
46
+ end
47
+
48
+ # Delete a file
49
+ # @param id [String] File ID
50
+ # @return [Boolean] Success status
51
+ def delete(id)
52
+ delete("/files/#{id}")
53
+ true
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Polar
6
+ module Resources
7
+ class LicenseKeys < Base
8
+ # List license keys
9
+ # @param params [Hash] Query parameters
10
+ # @option params [String] :organization_id Filter by organization ID
11
+ # @option params [String] :customer_id Filter by customer ID
12
+ # @option params [String] :benefit_id Filter by benefit ID
13
+ # @option params [Integer] :page Page number
14
+ # @option params [Integer] :limit Items per page
15
+ # @return [PaginatedResponse] Paginated list of license keys
16
+ def list(params = {})
17
+ paginate('/license-keys/', params)
18
+ end
19
+
20
+ # Get a license key by ID
21
+ # @param id [String] License key ID
22
+ # @return [Hash] License key data
23
+ def get(id)
24
+ response = get("/license-keys/#{id}")
25
+ response.body
26
+ end
27
+
28
+ # Update a license key
29
+ # @param id [String] License key ID
30
+ # @param attributes [Hash] Updated attributes
31
+ # @return [Hash] Updated license key
32
+ def update(id, attributes)
33
+ response = patch("/license-keys/#{id}", attributes)
34
+ response.body
35
+ end
36
+
37
+ # Get license key activation
38
+ # @param id [String] License key ID
39
+ # @param activation_id [String] Activation ID
40
+ # @return [Hash] Activation data
41
+ def get_activation(id, activation_id)
42
+ response = get("/license-keys/#{id}/activations/#{activation_id}")
43
+ response.body
44
+ end
45
+
46
+ # Validate a license key
47
+ # @param key [String] License key
48
+ # @param activation_id [String, nil] Optional activation ID
49
+ # @return [Hash] Validation result
50
+ def validate(key, activation_id: nil)
51
+ body = { key: key }
52
+ body[:activation_id] = activation_id if activation_id
53
+
54
+ response = post('/license-keys/validate', body)
55
+ response.body
56
+ end
57
+
58
+ # Activate a license key
59
+ # @param key [String] License key
60
+ # @param activation_data [Hash] Activation data
61
+ # @option activation_data [String] :label Activation label
62
+ # @option activation_data [Hash] :metadata Activation metadata
63
+ # @return [Hash] Activation result
64
+ def activate(key, activation_data = {})
65
+ body = { key: key }.merge(activation_data)
66
+ response = post('/license-keys/activate', body)
67
+ response.body
68
+ end
69
+
70
+ # Deactivate a license key
71
+ # @param key [String] License key
72
+ # @param activation_id [String] Activation ID
73
+ # @return [Boolean] Success status
74
+ def deactivate(key, activation_id)
75
+ body = { key: key, activation_id: activation_id }
76
+ post('/license-keys/deactivate', body)
77
+ true
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Polar
6
+ module Resources
7
+ class Metrics < Base
8
+ # Get metrics
9
+ # @param params [Hash] Query parameters
10
+ # @option params [String] :organization_id Organization ID
11
+ # @option params [String] :start_date Start date (ISO format)
12
+ # @option params [String] :end_date End date (ISO format)
13
+ # @option params [String] :interval Interval (day, week, month)
14
+ # @return [Hash] Metrics data
15
+ def get(params = {})
16
+ response = get('/metrics', params)
17
+ response.body
18
+ end
19
+
20
+ # Get metrics limits
21
+ # @param params [Hash] Query parameters
22
+ # @option params [String] :organization_id Organization ID
23
+ # @return [Hash] Metrics limits
24
+ def limits(params = {})
25
+ response = get('/metrics/limits', params)
26
+ response.body
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Polar
6
+ module Resources
7
+ class OAuth2 < Base
8
+ # OAuth2 authorize endpoint
9
+ # @param params [Hash] Authorization parameters
10
+ # @option params [String] :client_id Client ID
11
+ # @option params [String] :redirect_uri Redirect URI
12
+ # @option params [String] :response_type Response type (code)
13
+ # @option params [String] :scope Requested scopes
14
+ # @option params [String] :state State parameter
15
+ # @return [Hash] Authorization response
16
+ def authorize(params = {})
17
+ response = get('/oauth2/authorize', params)
18
+ response.body
19
+ end
20
+
21
+ # Request access token
22
+ # @param token_request [Hash] Token request data
23
+ # @option token_request [String] :grant_type Grant type
24
+ # @option token_request [String] :client_id Client ID
25
+ # @option token_request [String] :client_secret Client secret
26
+ # @option token_request [String] :code Authorization code (for authorization_code grant)
27
+ # @option token_request [String] :redirect_uri Redirect URI
28
+ # @return [Hash] Token response
29
+ def token(token_request)
30
+ response = post('/oauth2/token', token_request)
31
+ response.body
32
+ end
33
+
34
+ # Revoke token
35
+ # @param revoke_request [Hash] Revoke request data
36
+ # @option revoke_request [String] :token Token to revoke
37
+ # @option revoke_request [String] :token_type_hint Token type hint
38
+ # @return [Hash] Revoke response
39
+ def revoke(revoke_request)
40
+ response = post('/oauth2/revoke', revoke_request)
41
+ response.body
42
+ end
43
+
44
+ # Introspect token
45
+ # @param introspect_request [Hash] Introspect request data
46
+ # @option introspect_request [String] :token Token to introspect
47
+ # @return [Hash] Token introspection response
48
+ def introspect(introspect_request)
49
+ response = post('/oauth2/introspect', introspect_request)
50
+ response.body
51
+ end
52
+
53
+ # Get user info
54
+ # @return [Hash] User information
55
+ def userinfo
56
+ response = get('/oauth2/userinfo')
57
+ response.body
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Polar
6
+ module Resources
7
+ class Orders < Base
8
+ # List orders
9
+ # @param params [Hash] Query parameters
10
+ # @option params [String] :organization_id Filter by organization ID
11
+ # @option params [String] :customer_id Filter by customer ID
12
+ # @option params [String] :product_id Filter by product ID
13
+ # @option params [Integer] :page Page number
14
+ # @option params [Integer] :limit Items per page
15
+ # @return [PaginatedResponse] Paginated list of orders
16
+ def list(params = {})
17
+ paginate('/orders/', params)
18
+ end
19
+
20
+ # Get an order by ID
21
+ # @param id [String] Order ID
22
+ # @return [Hash] Order data
23
+ def get(id)
24
+ response = get("/orders/#{id}")
25
+ response.body
26
+ end
27
+
28
+ # Update an order
29
+ # @param id [String] Order ID
30
+ # @param attributes [Hash] Updated attributes
31
+ # @return [Hash] Updated order
32
+ def update(id, attributes)
33
+ response = patch("/orders/#{id}", attributes)
34
+ response.body
35
+ end
36
+
37
+ # Generate invoice for order
38
+ # @param id [String] Order ID
39
+ # @return [Hash] Invoice generation result
40
+ def generate_invoice(id)
41
+ response = post("/orders/#{id}/invoice")
42
+ response.body
43
+ end
44
+
45
+ # Get order invoice
46
+ # @param id [String] Order ID
47
+ # @return [Hash] Invoice data
48
+ def invoice(id)
49
+ response = get("/orders/#{id}/invoice")
50
+ response.body
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Polar
6
+ module Resources
7
+ class Organizations < Base
8
+ # List organizations
9
+ # @param params [Hash] Query parameters
10
+ # @return [PaginatedResponse] Paginated list of organizations
11
+ def list(params = {})
12
+ paginate('/organizations/', params)
13
+ end
14
+
15
+ # Create an organization
16
+ # @param attributes [Hash] Organization attributes
17
+ # @return [Hash] Created organization
18
+ def create(attributes)
19
+ response = post('/organizations/', attributes)
20
+ response.body
21
+ end
22
+
23
+ # Get an organization by ID
24
+ # @param id [String] Organization ID
25
+ # @return [Hash] Organization data
26
+ def get(id)
27
+ response = get("/organizations/#{id}")
28
+ response.body
29
+ end
30
+
31
+ # Update an organization
32
+ # @param id [String] Organization ID
33
+ # @param attributes [Hash] Updated attributes
34
+ # @return [Hash] Updated organization
35
+ def update(id, attributes)
36
+ response = patch("/organizations/#{id}", attributes)
37
+ response.body
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Polar
6
+ module Resources
7
+ class Payments < Base
8
+ # List payments
9
+ # @param params [Hash] Query parameters
10
+ # @option params [String] :organization_id Filter by organization ID
11
+ # @option params [String] :customer_id Filter by customer ID
12
+ # @option params [String] :order_id Filter by order ID
13
+ # @option params [Integer] :page Page number
14
+ # @option params [Integer] :limit Items per page
15
+ # @return [PaginatedResponse] Paginated list of payments
16
+ def list(params = {})
17
+ paginate('/payments/', params)
18
+ end
19
+
20
+ # Get a payment by ID
21
+ # @param id [String] Payment ID
22
+ # @return [Hash] Payment data
23
+ def get(id)
24
+ response = get("/payments/#{id}")
25
+ response.body
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Polar
6
+ module Resources
7
+ class Products < Base
8
+ # List products
9
+ # @param params [Hash] Query parameters
10
+ # @option params [String] :organization_id Filter by organization ID
11
+ # @option params [String] :query Search query
12
+ # @option params [Integer] :page Page number
13
+ # @option params [Integer] :limit Items per page
14
+ # @return [PaginatedResponse] Paginated list of products
15
+ def list(params = {})
16
+ paginate('/products/', params)
17
+ end
18
+
19
+ # Create a product
20
+ # @param attributes [Hash] Product attributes
21
+ # @option attributes [String] :name Product name
22
+ # @option attributes [String] :description Product description
23
+ # @option attributes [String] :organization_id Organization ID
24
+ # @option attributes [Array] :prices Product prices
25
+ # @return [Hash] Created product
26
+ def create(attributes)
27
+ response = post('/products/', attributes)
28
+ response.body
29
+ end
30
+
31
+ # Get a product by ID
32
+ # @param id [String] Product ID
33
+ # @return [Hash] Product data
34
+ def get(id)
35
+ response = get("/products/#{id}")
36
+ response.body
37
+ end
38
+
39
+ # Update a product
40
+ # @param id [String] Product ID
41
+ # @param attributes [Hash] Updated attributes
42
+ # @return [Hash] Updated product
43
+ def update(id, attributes)
44
+ response = patch("/products/#{id}", attributes)
45
+ response.body
46
+ end
47
+
48
+ # Update product benefits
49
+ # @param id [String] Product ID
50
+ # @param benefits [Array] List of benefit IDs
51
+ # @return [Hash] Updated product
52
+ def update_benefits(id, benefits)
53
+ response = post("/products/#{id}/benefits", { benefits: benefits })
54
+ response.body
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Polar
6
+ module Resources
7
+ class Subscriptions < Base
8
+ # List subscriptions
9
+ # @param params [Hash] Query parameters
10
+ # @option params [String] :organization_id Filter by organization ID
11
+ # @option params [String] :customer_id Filter by customer ID
12
+ # @option params [String] :product_id Filter by product ID
13
+ # @option params [String] :status Filter by status
14
+ # @option params [Integer] :page Page number
15
+ # @option params [Integer] :limit Items per page
16
+ # @return [PaginatedResponse] Paginated list of subscriptions
17
+ def list(params = {})
18
+ paginate('/subscriptions/', params)
19
+ end
20
+
21
+ # Export subscriptions
22
+ # @param params [Hash] Export parameters
23
+ # @return [Hash] Export job details
24
+ def export(params = {})
25
+ response = post('/subscriptions/export', params)
26
+ response.body
27
+ end
28
+
29
+ # Get a subscription by ID
30
+ # @param id [String] Subscription ID
31
+ # @return [Hash] Subscription data
32
+ def get(id)
33
+ response = get("/subscriptions/#{id}")
34
+ response.body
35
+ end
36
+
37
+ # Update a subscription
38
+ # @param id [String] Subscription ID
39
+ # @param attributes [Hash] Updated attributes
40
+ # @return [Hash] Updated subscription
41
+ def update(id, attributes)
42
+ response = patch("/subscriptions/#{id}", attributes)
43
+ response.body
44
+ end
45
+
46
+ # Revoke (cancel) a subscription
47
+ # @param id [String] Subscription ID
48
+ # @return [Hash] Revoked subscription
49
+ def revoke(id)
50
+ response = post("/subscriptions/#{id}/revoke")
51
+ response.body
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Polar
6
+ module Resources
7
+ class Webhooks < Base
8
+ # List webhook endpoints
9
+ # @param params [Hash] Query parameters
10
+ # @option params [String] :organization_id Filter by organization ID
11
+ # @option params [Integer] :page Page number
12
+ # @option params [Integer] :limit Items per page
13
+ # @return [PaginatedResponse] Paginated list of webhook endpoints
14
+ def list_webhook_endpoints(params = {})
15
+ paginate('/webhooks/endpoints', params)
16
+ end
17
+
18
+ # Create webhook endpoint
19
+ # @param attributes [Hash] Webhook endpoint attributes
20
+ # @option attributes [String] :url Webhook URL
21
+ # @option attributes [Array] :events List of events to subscribe to
22
+ # @option attributes [String] :organization_id Organization ID
23
+ # @return [Hash] Created webhook endpoint
24
+ def create_webhook_endpoint(attributes)
25
+ response = post('/webhooks/endpoints', attributes)
26
+ response.body
27
+ end
28
+
29
+ # Get webhook endpoint
30
+ # @param id [String] Webhook endpoint ID
31
+ # @return [Hash] Webhook endpoint data
32
+ def get_webhook_endpoint(id)
33
+ response = get("/webhooks/endpoints/#{id}")
34
+ response.body
35
+ end
36
+
37
+ # Update webhook endpoint
38
+ # @param id [String] Webhook endpoint ID
39
+ # @param attributes [Hash] Updated attributes
40
+ # @return [Hash] Updated webhook endpoint
41
+ def update_webhook_endpoint(id, attributes)
42
+ response = patch("/webhooks/endpoints/#{id}", attributes)
43
+ response.body
44
+ end
45
+
46
+ # Delete webhook endpoint
47
+ # @param id [String] Webhook endpoint ID
48
+ # @return [Boolean] Success status
49
+ def delete_webhook_endpoint(id)
50
+ delete("/webhooks/endpoints/#{id}")
51
+ true
52
+ end
53
+
54
+ # Reset webhook endpoint secret
55
+ # @param id [String] Webhook endpoint ID
56
+ # @return [Hash] Updated webhook endpoint with new secret
57
+ def reset_webhook_endpoint_secret(id)
58
+ response = post("/webhooks/endpoints/#{id}/secret/reset")
59
+ response.body
60
+ end
61
+
62
+ # List webhook deliveries
63
+ # @param params [Hash] Query parameters
64
+ # @option params [String] :endpoint_id Filter by endpoint ID
65
+ # @option params [Integer] :page Page number
66
+ # @option params [Integer] :limit Items per page
67
+ # @return [PaginatedResponse] Paginated list of webhook deliveries
68
+ def list_webhook_deliveries(params = {})
69
+ paginate('/webhooks/deliveries', params)
70
+ end
71
+
72
+ # Redeliver webhook event
73
+ # @param delivery_id [String] Webhook delivery ID
74
+ # @return [Hash] Redelivery result
75
+ def redeliver_webhook_event(delivery_id)
76
+ response = post("/webhooks/deliveries/#{delivery_id}/redeliver")
77
+ response.body
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Polar
4
+ VERSION = '0.1.0'
5
+ end