growsurf-python 1.15.1__tar.gz → 1.17.0__tar.gz

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 (220) hide show
  1. growsurf_python-1.17.0/.release-please-manifest.json +3 -0
  2. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/CHANGELOG.md +31 -0
  3. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/PKG-INFO +1 -1
  4. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/api.md +19 -0
  5. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/pyproject.toml +1 -1
  6. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/requirements-dev.lock +1 -1
  7. growsurf_python-1.17.0/src/growsurf/_exceptions.py +199 -0
  8. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_version.py +1 -1
  9. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/resources/campaign/__init__.py +14 -0
  10. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/resources/campaign/campaign.py +73 -25
  11. growsurf_python-1.17.0/src/growsurf/resources/campaign/custom_domain.py +450 -0
  12. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/resources/campaign/design.py +12 -6
  13. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/resources/campaign/emails.py +4 -4
  14. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/resources/campaign/installation.py +4 -4
  15. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/resources/campaign/options.py +10 -10
  16. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/resources/campaign/participant.py +52 -32
  17. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/resources/campaign/rewards.py +76 -16
  18. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/resources/campaign/webhooks.py +40 -8
  19. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/resources/team.py +34 -2
  20. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/__init__.py +8 -0
  21. growsurf_python-1.17.0/src/growsurf/types/campaign/campaign_custom_domain.py +49 -0
  22. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/campaign_design.py +19 -12
  23. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/campaign_options.py +1 -1
  24. growsurf_python-1.17.0/src/growsurf/types/campaign/custom_domain_set_params.py +15 -0
  25. growsurf_python-1.17.0/src/growsurf/types/campaign/delete_campaign_custom_domain_response.py +13 -0
  26. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant.py +25 -64
  27. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_add_params.py +13 -3
  28. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_email_params.py +11 -8
  29. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_get_payout_destination_response.py +8 -5
  30. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_list_referrals_params.py +1 -1
  31. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_request_payout_destination_confirmation_response.py +1 -1
  32. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/reward_create_params.py +26 -6
  33. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/reward_update_params.py +26 -6
  34. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/webhook_create_params.py +11 -1
  35. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_create_mobile_participant_token_params.py +13 -3
  36. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_create_params.py +10 -5
  37. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_list_referrals_params.py +1 -1
  38. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_update_params.py +3 -2
  39. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/commission_structure.py +5 -0
  40. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/referral_flow_screenshot.py +8 -7
  41. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/referral_list.py +12 -0
  42. growsurf_python-1.17.0/tests/api_resources/campaign/test_custom_domain.py +127 -0
  43. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/api_resources/campaign/test_participant.py +2 -0
  44. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/api_resources/test_campaign.py +2 -0
  45. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/uv.lock +305 -239
  46. growsurf_python-1.15.1/.release-please-manifest.json +0 -3
  47. growsurf_python-1.15.1/src/growsurf/_exceptions.py +0 -108
  48. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/.gitignore +0 -0
  49. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/CONTRIBUTING.md +0 -0
  50. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/LICENSE +0 -0
  51. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/README.md +0 -0
  52. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/SECURITY.md +0 -0
  53. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/bin/check-release-environment +0 -0
  54. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/bin/publish-pypi +0 -0
  55. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/examples/.keep +0 -0
  56. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/release-please-config.json +0 -0
  57. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/__init__.py +0 -0
  58. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_base_client.py +0 -0
  59. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_client.py +0 -0
  60. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_compat.py +0 -0
  61. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_constants.py +0 -0
  62. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_files.py +0 -0
  63. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_models.py +0 -0
  64. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_qs.py +0 -0
  65. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_resource.py +0 -0
  66. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_response.py +0 -0
  67. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_streaming.py +0 -0
  68. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_types.py +0 -0
  69. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_utils/__init__.py +0 -0
  70. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_utils/_compat.py +0 -0
  71. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_utils/_datetime_parse.py +0 -0
  72. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_utils/_json.py +0 -0
  73. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_utils/_logs.py +0 -0
  74. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_utils/_path.py +0 -0
  75. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_utils/_proxy.py +0 -0
  76. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_utils/_reflection.py +0 -0
  77. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_utils/_resources_proxy.py +0 -0
  78. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_utils/_streams.py +0 -0
  79. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_utils/_sync.py +0 -0
  80. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_utils/_transform.py +0 -0
  81. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_utils/_typing.py +0 -0
  82. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/_utils/_utils.py +0 -0
  83. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/lib/.keep +0 -0
  84. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/py.typed +0 -0
  85. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/resources/__init__.py +0 -0
  86. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/resources/account.py +0 -0
  87. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/resources/campaign/commission.py +0 -0
  88. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/resources/campaign/integrations.py +0 -0
  89. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/resources/campaign/program_resources.py +0 -0
  90. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/resources/campaign/reward.py +0 -0
  91. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/__init__.py +0 -0
  92. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/account_create_params.py +0 -0
  93. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/affiliate_application.py +0 -0
  94. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/affiliate_application_answer.py +0 -0
  95. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/affiliate_application_list_response.py +0 -0
  96. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/affiliate_invite.py +0 -0
  97. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/affiliate_invite_list_response.py +0 -0
  98. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/analytics_availability.py +0 -0
  99. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/analytics_unavailable_reason.py +0 -0
  100. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/campaign.py +0 -0
  101. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/campaign_emails.py +0 -0
  102. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/campaign_installation.py +0 -0
  103. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/campaign_reward_list_response.py +0 -0
  104. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/commission_approve_response.py +0 -0
  105. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/commission_delete_response.py +0 -0
  106. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/delete_program_resource_response.py +0 -0
  107. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/delete_reward_response.py +0 -0
  108. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/delete_webhook_response.py +0 -0
  109. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/email_participant_response.py +0 -0
  110. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/fraud_risk_level.py +0 -0
  111. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/integration.py +0 -0
  112. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/integration_list_response.py +0 -0
  113. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/language.py +0 -0
  114. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_activation_analytics.py +0 -0
  115. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_activity_logs_response.py +0 -0
  116. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_analytics_params.py +0 -0
  117. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_analytics_response.py +0 -0
  118. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_bulk_delete_params.py +0 -0
  119. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_bulk_delete_response.py +0 -0
  120. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_delete_response.py +0 -0
  121. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_list_activity_logs_params.py +0 -0
  122. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_list_commissions_params.py +0 -0
  123. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_list_payouts_params.py +0 -0
  124. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_list_rewards_params.py +0 -0
  125. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_list_rewards_response.py +0 -0
  126. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_record_transaction_params.py +0 -0
  127. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_record_transaction_response.py +0 -0
  128. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_refund_transaction_params.py +0 -0
  129. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_refund_transaction_response.py +0 -0
  130. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_request_payout_destination_confirmation_params.py +0 -0
  131. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_reward.py +0 -0
  132. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_send_invites_params.py +0 -0
  133. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_send_invites_response.py +0 -0
  134. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_trigger_referral_params.py +0 -0
  135. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_trigger_referral_response.py +0 -0
  136. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/participant_update_params.py +0 -0
  137. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/pending_analytics_erasure.py +0 -0
  138. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/program_resource.py +0 -0
  139. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/program_resource_list_response.py +0 -0
  140. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/program_resource_upload_result.py +0 -0
  141. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/program_resource_upload_ticket.py +0 -0
  142. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/referral_source.py +0 -0
  143. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/referral_status.py +0 -0
  144. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/reward.py +0 -0
  145. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/reward_approve_params.py +0 -0
  146. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/reward_approve_response.py +0 -0
  147. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/reward_delete_response.py +0 -0
  148. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/reward_fulfill_response.py +0 -0
  149. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/reward_tax_valuation.py +0 -0
  150. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/webhook.py +0 -0
  151. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/webhook_event.py +0 -0
  152. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/webhook_list_response.py +0 -0
  153. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/webhook_test_params.py +0 -0
  154. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/webhook_test_response.py +0 -0
  155. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign/webhook_update_params.py +0 -0
  156. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_activation_analytics_response.py +0 -0
  157. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_create_affiliate_invite_params.py +0 -0
  158. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_create_mobile_participant_token_response.py +0 -0
  159. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_engagement_analytics.py +0 -0
  160. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_list_affiliate_applications_params.py +0 -0
  161. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_list_affiliate_invites_params.py +0 -0
  162. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_list_commissions_params.py +0 -0
  163. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_list_leaderboard_params.py +0 -0
  164. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_list_participants_params.py +0 -0
  165. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_list_payouts_params.py +0 -0
  166. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_list_response.py +0 -0
  167. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_retrieve_activation_analytics_params.py +0 -0
  168. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_retrieve_analytics_params.py +0 -0
  169. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_retrieve_analytics_response.py +0 -0
  170. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/campaign_review_affiliate_application_params.py +0 -0
  171. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/create_account_response.py +0 -0
  172. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/email_analytics.py +0 -0
  173. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/participant_commission_list.py +0 -0
  174. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/participant_list.py +0 -0
  175. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/participant_payout_list.py +0 -0
  176. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/referral_flow_screenshots_response.py +0 -0
  177. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/rotate_api_key_response.py +0 -0
  178. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/team.py +0 -0
  179. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/team_update_params.py +0 -0
  180. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/src/growsurf/types/verification_email_response.py +0 -0
  181. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/__init__.py +0 -0
  182. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/api_resources/__init__.py +0 -0
  183. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/api_resources/campaign/__init__.py +0 -0
  184. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/api_resources/campaign/test_commission.py +0 -0
  185. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/api_resources/campaign/test_design.py +0 -0
  186. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/api_resources/campaign/test_emails.py +0 -0
  187. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/api_resources/campaign/test_installation.py +0 -0
  188. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/api_resources/campaign/test_integrations.py +0 -0
  189. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/api_resources/campaign/test_options.py +0 -0
  190. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/api_resources/campaign/test_program_resources.py +0 -0
  191. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/api_resources/campaign/test_reward.py +0 -0
  192. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/api_resources/campaign/test_rewards.py +0 -0
  193. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/api_resources/campaign/test_webhooks.py +0 -0
  194. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/api_resources/test_account.py +0 -0
  195. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/api_resources/test_team_contract.py +0 -0
  196. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/conftest.py +0 -0
  197. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/sample_file.txt +0 -0
  198. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/test_client.py +0 -0
  199. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/test_extract_files.py +0 -0
  200. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/test_files.py +0 -0
  201. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/test_models.py +0 -0
  202. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/test_qs.py +0 -0
  203. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/test_required_args.py +0 -0
  204. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/test_response.py +0 -0
  205. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/test_streaming.py +0 -0
  206. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/test_transform.py +0 -0
  207. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/test_utils/test_datetime_parse.py +0 -0
  208. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/test_utils/test_json.py +0 -0
  209. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/test_utils/test_path.py +0 -0
  210. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/test_utils/test_proxy.py +0 -0
  211. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/test_utils/test_typing.py +0 -0
  212. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/types/test_affiliate_application.py +0 -0
  213. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/types/test_analytics_reward_status.py +0 -0
  214. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/types/test_email_analytics.py +0 -0
  215. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/types/test_lead_reward_events.py +0 -0
  216. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/types/test_participant_activation_engagement_analytics.py +0 -0
  217. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/types/test_participant_contract.py +0 -0
  218. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/types/test_payout_provider_forward_compat.py +0 -0
  219. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/types/test_referral_source.py +0 -0
  220. {growsurf_python-1.15.1 → growsurf_python-1.17.0}/tests/utils.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "1.17.0"
3
+ }
@@ -1,5 +1,36 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.17.0](https://github.com/growsurf/growsurf-python/compare/v1.16.0...v1.17.0) (2026-11-03)
4
+
5
+
6
+ ### Features
7
+
8
+ * add Tint and Glass program styles ([a975c13](https://github.com/growsurf/growsurf-python/commit/a975c13b267bf97ff9d57f26673f92bc29642b35))
9
+ * **api:** add languages.flagCountries to Campaign Options ([d5663f0](https://github.com/growsurf/growsurf-python/commit/d5663f08a9fa3e4ec421a90af9b4491ba4eb6dc4))
10
+ * **api:** sync REST v2 contract changes ([2a0e777](https://github.com/growsurf/growsurf-python/commit/2a0e7778a0bdddadbdfe7b55c225723d2c813d02))
11
+ * expose documented error-body fields and sync campaign and participant models ([65db348](https://github.com/growsurf/growsurf-python/commit/65db34829db847313e17757832f6d8f2324535ba))
12
+ * expose program visual style in campaign design ([0d93f91](https://github.com/growsurf/growsurf-python/commit/0d93f917180557f492016acc623cf449962b7120))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * **deps:** bump aiohttp to 3.14.5 and certifi to 2026.10.23 for security advisories ([c9640ee](https://github.com/growsurf/growsurf-python/commit/c9640eeb58f96838f52b3b24f2168a24b5402e74))
18
+
19
+
20
+ ### Documentation
21
+
22
+ * clarify Add Participant claim-offer wording and page title defaults ([5fc74e8](https://github.com/growsurf/growsurf-python/commit/5fc74e8666defb009a7870ee20701c0ce8ca0506))
23
+ * clarify referral reward metadata amounts ([1bf9897](https://github.com/growsurf/growsurf-python/commit/1bf9897e437a67f4c912fcec24f234d24ebbf155))
24
+ * correct default program style ([4f6bbd5](https://github.com/growsurf/growsurf-python/commit/4f6bbd5425ceb84889d14ddd70b0e2653ef94f04))
25
+
26
+ ## [1.16.0](https://github.com/growsurf/growsurf-python/compare/v1.15.1...v1.16.0) (2026-10-19)
27
+
28
+
29
+ ### Features
30
+
31
+ * support resource empty-state graphics ([afba1c2](https://github.com/growsurf/growsurf-python/commit/afba1c2730e504d8b1410c110ddb76e4fe5551d0))
32
+ * support resource empty-state graphics ([5898cd4](https://github.com/growsurf/growsurf-python/commit/5898cd4f8df39e538b31ee0c28363b82b0149aa4))
33
+
3
34
  ## [1.15.1](https://github.com/growsurf/growsurf-python/compare/v1.15.0...v1.15.1) (2026-10-19)
4
35
 
5
36
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: growsurf-python
3
- Version: 1.15.1
3
+ Version: 1.17.0
4
4
  Summary: The official Python library for the growsurf API
5
5
  Project-URL: Homepage, https://growsurf.com/
6
6
  Project-URL: Repository, https://github.com/growsurf/growsurf-python
@@ -287,3 +287,22 @@ Methods:
287
287
 
288
288
  - <code title="get /campaign/{id}/installation">client.campaign.installation.<a href="./src/growsurf/resources/campaign/installation.py">retrieve</a>(id) -> <a href="./src/growsurf/types/campaign/campaign_installation.py">CampaignInstallation</a></code>
289
289
  - <code title="patch /campaign/{id}/installation">client.campaign.installation.<a href="./src/growsurf/resources/campaign/installation.py">update</a>(id, \*, body) -> <a href="./src/growsurf/types/campaign/campaign_installation.py">CampaignInstallation</a></code>
290
+
291
+ ## CustomDomain
292
+
293
+ Types:
294
+
295
+ ```python
296
+ from growsurf.types.campaign import (
297
+ CampaignCustomDomain,
298
+ CampaignCustomDomainDNSRecord,
299
+ DeleteCampaignCustomDomainResponse,
300
+ )
301
+ ```
302
+
303
+ Methods:
304
+
305
+ - <code title="get /campaign/{id}/custom-domain">client.campaign.custom_domain.<a href="./src/growsurf/resources/campaign/custom_domain.py">retrieve</a>(id) -> <a href="./src/growsurf/types/campaign/campaign_custom_domain.py">CampaignCustomDomain</a></code>
306
+ - <code title="put /campaign/{id}/custom-domain">client.campaign.custom_domain.<a href="./src/growsurf/resources/campaign/custom_domain.py">set</a>(id, \*\*<a href="src/growsurf/types/campaign/custom_domain_set_params.py">params</a>) -> <a href="./src/growsurf/types/campaign/campaign_custom_domain.py">CampaignCustomDomain</a></code>
307
+ - <code title="post /campaign/{id}/custom-domain/verify">client.campaign.custom_domain.<a href="./src/growsurf/resources/campaign/custom_domain.py">verify</a>(id) -> <a href="./src/growsurf/types/campaign/campaign_custom_domain.py">CampaignCustomDomain</a></code>
308
+ - <code title="delete /campaign/{id}/custom-domain">client.campaign.custom_domain.<a href="./src/growsurf/resources/campaign/custom_domain.py">delete</a>(id) -> <a href="./src/growsurf/types/campaign/delete_campaign_custom_domain_response.py">DeleteCampaignCustomDomainResponse</a></code>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "growsurf-python"
3
- version = "1.15.1"
3
+ version = "1.17.0"
4
4
  description = "The official Python library for the growsurf API"
5
5
  dynamic = ["readme"]
6
6
  license = "Apache-2.0"
@@ -9,7 +9,7 @@ anyio==4.15.1
9
9
  # httpx
10
10
  backports-asyncio-runner==1.2.0 ; python_full_version < '3.11'
11
11
  # via pytest-asyncio
12
- certifi==2026.1.4
12
+ certifi==2026.10.23
13
13
  # via
14
14
  # httpcore
15
15
  # httpx
@@ -0,0 +1,199 @@
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 Dict, List, cast
6
+ from typing_extensions import Literal
7
+
8
+ import httpx
9
+
10
+ __all__ = [
11
+ "BadRequestError",
12
+ "AuthenticationError",
13
+ "PermissionDeniedError",
14
+ "NotFoundError",
15
+ "ConflictError",
16
+ "UnprocessableEntityError",
17
+ "RateLimitError",
18
+ "InternalServerError",
19
+ ]
20
+
21
+
22
+ class GrowsurfError(Exception):
23
+ pass
24
+
25
+
26
+ class APIError(GrowsurfError):
27
+ message: str
28
+ request: httpx.Request
29
+
30
+ body: object | None
31
+ """The API response body.
32
+
33
+ If the API responded with a valid JSON structure then this property will be the
34
+ decoded result.
35
+
36
+ If it isn't a valid JSON structure then this will be the raw response.
37
+
38
+ If there was no response associated with this error then it will be `None`.
39
+ """
40
+
41
+ def __init__(self, message: str, request: httpx.Request, *, body: object | None) -> None: # noqa: ARG002
42
+ super().__init__(message)
43
+ self.request = request
44
+ self.message = message
45
+ self.body = body
46
+
47
+
48
+ class APIResponseValidationError(APIError):
49
+ response: httpx.Response
50
+ status_code: int
51
+
52
+ def __init__(self, response: httpx.Response, body: object | None, *, message: str | None = None) -> None:
53
+ super().__init__(message or "Data returned by API invalid for expected schema.", response.request, body=body)
54
+ self.response = response
55
+ self.status_code = response.status_code
56
+
57
+
58
+ class APIStatusError(APIError):
59
+ """Raised when an API response has a status code of 4xx or 5xx."""
60
+
61
+ response: httpx.Response
62
+ status_code: int
63
+
64
+ # Documented error-body fields. Each is `None` when the body omits it or sends another
65
+ # type; `body` keeps the complete response body, including fields added later.
66
+ error_name: str | None
67
+ """Error name returned for the failed request."""
68
+
69
+ error_code: str | None
70
+ """Stable machine-readable error code."""
71
+
72
+ error_message: str | None
73
+ """Human-readable error message."""
74
+
75
+ errors: List[Dict[str, object]] | None
76
+ """Optional validation details for specific request fields."""
77
+
78
+ support_url: str | None
79
+ """Support URL related to the error, when available."""
80
+
81
+ policy_name: str | None
82
+ """Rate-limit policy name for `429` errors, when available."""
83
+
84
+ level: str | None
85
+ """Error severity level, when available."""
86
+
87
+ timestamp: str | None
88
+ """When the error response was created."""
89
+
90
+ fraud_risk_level: str | None
91
+ """Fraud risk level assigned to the blocked signup."""
92
+
93
+ fraud_reason_code: str | None
94
+ """Machine-readable reason code for the fraud decision."""
95
+
96
+ matched_participant_ids: List[str] | None
97
+ """Existing participant IDs related to the fraud match."""
98
+
99
+ email: str | None
100
+ """Email address from the blocked signup attempt."""
101
+
102
+ referrer_id: str | None
103
+ """Referrer participant ID supplied with the blocked signup, or `null`."""
104
+
105
+ ip_address: str | None
106
+ """IP address supplied with the blocked signup, or `null`."""
107
+
108
+ fingerprint: str | None
109
+ """Browser fingerprint supplied with the blocked signup, or `null`."""
110
+
111
+ blocked_at: str | None
112
+ """When the signup was blocked."""
113
+
114
+ def __init__(self, message: str, *, response: httpx.Response, body: object | None) -> None:
115
+ super().__init__(message, response.request, body=body)
116
+ self.response = response
117
+ self.status_code = response.status_code
118
+
119
+ fields = cast(Dict[str, object], body) if isinstance(body, dict) else {}
120
+ self.error_name = _str_or_none(fields.get("name"))
121
+ self.error_code = _str_or_none(fields.get("code"))
122
+ self.error_message = _str_or_none(fields.get("message"))
123
+ self.errors = _record_list_or_none(fields.get("errors"))
124
+ self.support_url = _str_or_none(fields.get("supportUrl"))
125
+ self.policy_name = _str_or_none(fields.get("policyName"))
126
+ self.level = _str_or_none(fields.get("level"))
127
+ self.timestamp = _str_or_none(fields.get("timestamp"))
128
+ self.fraud_risk_level = _str_or_none(fields.get("fraudRiskLevel"))
129
+ self.fraud_reason_code = _str_or_none(fields.get("fraudReasonCode"))
130
+ self.matched_participant_ids = _str_list_or_none(fields.get("matchedParticipantIds"))
131
+ self.email = _str_or_none(fields.get("email"))
132
+ self.referrer_id = _str_or_none(fields.get("referrerId"))
133
+ self.ip_address = _str_or_none(fields.get("ipAddress"))
134
+ self.fingerprint = _str_or_none(fields.get("fingerprint"))
135
+ self.blocked_at = _str_or_none(fields.get("blockedAt"))
136
+
137
+
138
+ class APIConnectionError(APIError):
139
+ def __init__(self, *, message: str = "Connection error.", request: httpx.Request) -> None:
140
+ super().__init__(message, request, body=None)
141
+
142
+
143
+ class APITimeoutError(APIConnectionError):
144
+ def __init__(self, request: httpx.Request) -> None:
145
+ super().__init__(message="Request timed out.", request=request)
146
+
147
+
148
+ class BadRequestError(APIStatusError):
149
+ status_code: Literal[400] = 400 # pyright: ignore[reportIncompatibleVariableOverride]
150
+
151
+
152
+ class AuthenticationError(APIStatusError):
153
+ status_code: Literal[401] = 401 # pyright: ignore[reportIncompatibleVariableOverride]
154
+
155
+
156
+ class PermissionDeniedError(APIStatusError):
157
+ status_code: Literal[403] = 403 # pyright: ignore[reportIncompatibleVariableOverride]
158
+
159
+
160
+ class NotFoundError(APIStatusError):
161
+ status_code: Literal[404] = 404 # pyright: ignore[reportIncompatibleVariableOverride]
162
+
163
+
164
+ class ConflictError(APIStatusError):
165
+ status_code: Literal[409] = 409 # pyright: ignore[reportIncompatibleVariableOverride]
166
+
167
+
168
+ class UnprocessableEntityError(APIStatusError):
169
+ status_code: Literal[422] = 422 # pyright: ignore[reportIncompatibleVariableOverride]
170
+
171
+
172
+ class RateLimitError(APIStatusError):
173
+ status_code: Literal[429] = 429 # pyright: ignore[reportIncompatibleVariableOverride]
174
+
175
+
176
+ class InternalServerError(APIStatusError):
177
+ pass
178
+
179
+
180
+ def _str_or_none(value: object) -> str | None:
181
+ return value if isinstance(value, str) else None
182
+
183
+
184
+ def _str_list_or_none(value: object) -> List[str] | None:
185
+ if not isinstance(value, list):
186
+ return None
187
+ items = cast(List[object], value)
188
+ if not all(isinstance(item, str) for item in items):
189
+ return None
190
+ return cast(List[str], items)
191
+
192
+
193
+ def _record_list_or_none(value: object) -> List[Dict[str, object]] | None:
194
+ if not isinstance(value, list):
195
+ return None
196
+ items = cast(List[object], value)
197
+ if not all(isinstance(item, dict) for item in items):
198
+ return None
199
+ return cast(List[Dict[str, object]], items)
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "growsurf"
4
- __version__ = "1.15.1" # x-release-please-version
4
+ __version__ = "1.17.0" # x-release-please-version
@@ -88,6 +88,14 @@ from .integrations import (
88
88
  IntegrationsResourceWithStreamingResponse,
89
89
  AsyncIntegrationsResourceWithStreamingResponse,
90
90
  )
91
+ from .custom_domain import (
92
+ CustomDomainResource,
93
+ AsyncCustomDomainResource,
94
+ CustomDomainResourceWithRawResponse,
95
+ AsyncCustomDomainResourceWithRawResponse,
96
+ CustomDomainResourceWithStreamingResponse,
97
+ AsyncCustomDomainResourceWithStreamingResponse,
98
+ )
91
99
  from .program_resources import (
92
100
  ProgramResourcesResource,
93
101
  AsyncProgramResourcesResource,
@@ -158,6 +166,12 @@ __all__ = [
158
166
  "AsyncInstallationResourceWithRawResponse",
159
167
  "InstallationResourceWithStreamingResponse",
160
168
  "AsyncInstallationResourceWithStreamingResponse",
169
+ "CustomDomainResource",
170
+ "AsyncCustomDomainResource",
171
+ "CustomDomainResourceWithRawResponse",
172
+ "AsyncCustomDomainResourceWithRawResponse",
173
+ "CustomDomainResourceWithStreamingResponse",
174
+ "AsyncCustomDomainResourceWithStreamingResponse",
161
175
  "CommissionResource",
162
176
  "AsyncCommissionResource",
163
177
  "CommissionResourceWithRawResponse",
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Dict, Iterable
5
+ from typing import Dict, Iterable, Optional
6
6
  from typing_extensions import Literal
7
7
 
8
8
  import httpx
@@ -113,6 +113,14 @@ from .integrations import (
113
113
  IntegrationsResourceWithStreamingResponse,
114
114
  AsyncIntegrationsResourceWithStreamingResponse,
115
115
  )
116
+ from .custom_domain import (
117
+ CustomDomainResource,
118
+ AsyncCustomDomainResource,
119
+ CustomDomainResourceWithRawResponse,
120
+ AsyncCustomDomainResourceWithRawResponse,
121
+ CustomDomainResourceWithStreamingResponse,
122
+ AsyncCustomDomainResourceWithStreamingResponse,
123
+ )
116
124
  from ..._base_client import make_request_options
117
125
  from ...types.campaign import ReferralStatus, reward_create_params
118
126
  from .program_resources import (
@@ -197,6 +205,11 @@ class CampaignResource(SyncAPIResource):
197
205
  """Campaign installation (`CampaignInstallation`) — the Program Editor's Installation tab."""
198
206
  return InstallationResource(self._client)
199
207
 
208
+ @cached_property
209
+ def custom_domain(self) -> CustomDomainResource:
210
+ """Campaign custom domain (`CampaignCustomDomain`) — the domain that serves a program's landing pages."""
211
+ return CustomDomainResource(self._client)
212
+
200
213
  @cached_property
201
214
  def with_raw_response(self) -> CampaignResourceWithRawResponse:
202
215
  """
@@ -220,8 +233,8 @@ class CampaignResource(SyncAPIResource):
220
233
  self,
221
234
  *,
222
235
  type: Literal["REFERRAL", "AFFILIATE"],
223
- company_logo_image_url: str | Omit = omit,
224
- company_name: str | Omit = omit,
236
+ company_logo_image_url: Optional[str] | Omit = omit,
237
+ company_name: Optional[str] | Omit = omit,
225
238
  currency_iso: str | Omit = omit,
226
239
  goal: Literal[
227
240
  "CUSTOMERS",
@@ -329,8 +342,8 @@ class CampaignResource(SyncAPIResource):
329
342
  self,
330
343
  id: str,
331
344
  *,
332
- company_logo_image_url: str | Omit = omit,
333
- company_name: str | Omit = omit,
345
+ company_logo_image_url: Optional[str] | Omit = omit,
346
+ company_name: Optional[str] | Omit = omit,
334
347
  name: str | Omit = omit,
335
348
  status: Literal["IN_PROGRESS", "COMPLETE"] | Omit = omit,
336
349
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -347,8 +360,8 @@ class CampaignResource(SyncAPIResource):
347
360
  dedicated config sub-resources, not here. The program cannot be deleted via this
348
361
  endpoint.
349
362
  Changes to participant email content are checked before saving. Rejected content returns
350
- `400`; if the check is unavailable, `503` asks you to retry. Neither response saves the
351
- change. A concurrent edit can return `409`; reload the program before retrying.
363
+ `400` and is not saved. A concurrent edit can return `409`; reload the program before
364
+ retrying.
352
365
 
353
366
  Args:
354
367
  status: The requested program status. `IN_PROGRESS` publishes or resumes the program;
@@ -449,6 +462,7 @@ class CampaignResource(SyncAPIResource):
449
462
  metadata: Dict[str, object] | Omit = omit,
450
463
  mobile_instance_id: str | Omit = omit,
451
464
  referral_status: Literal["CREDIT_PENDING", "CREDIT_AWARDED"] | Omit = omit,
465
+ referred_at: Optional[int] | Omit = omit,
452
466
  referred_by: str | Omit = omit,
453
467
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
454
468
  # The extra values given here take precedence over values defined on the client or passed to this method.
@@ -472,8 +486,14 @@ class CampaignResource(SyncAPIResource):
472
486
 
473
487
  is_affiliate: Affiliate programs only. Controls affiliate enrollment for a new participant.
474
488
 
475
- language: The language of the participant's portal and program emails. Must be one of the
476
- program's languages. Applied only when this request creates the participant.
489
+ language: The language of the participant's portal and program emails. Stored when it is one of
490
+ the program's languages. A regional tag maps to its language (for example, `es-MX` is
491
+ stored as `es`). Any other value is ignored and the program's base language applies.
492
+ Applied only when this request creates the participant.
493
+
494
+ referred_at: When the participant was referred, in Unix milliseconds. Used only with a valid
495
+ `referredBy`. If you omit `referralStatus`, GrowSurf compares this time with the
496
+ program's referral credit window to set it. Defaults to the time of the request.
477
497
 
478
498
  referred_by: Referrer participant ID or email address.
479
499
 
@@ -501,6 +521,7 @@ class CampaignResource(SyncAPIResource):
501
521
  "metadata": metadata,
502
522
  "mobile_instance_id": mobile_instance_id,
503
523
  "referral_status": referral_status,
524
+ "referred_at": referred_at,
504
525
  "referred_by": referred_by,
505
526
  },
506
527
  campaign_create_mobile_participant_token_params.CampaignCreateMobileParticipantTokenParams,
@@ -793,10 +814,7 @@ class CampaignResource(SyncAPIResource):
793
814
  next_id: str | Omit = omit,
794
815
  offset: int | Omit = omit,
795
816
  referral_status: ReferralStatus | Omit = omit,
796
- sort_by: Literal[
797
- "updatedAt", "createdAt", "email", "firstName", "lastName", "referralStatus", "referralTriggeredAt"
798
- ]
799
- | Omit = omit,
817
+ sort_by: Literal["updatedAt", "createdAt", "email", "referralTriggeredAt"] | Omit = omit,
800
818
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
801
819
  # The extra values given here take precedence over values defined on the client or passed to this method.
802
820
  extra_headers: Headers | None = None,
@@ -1432,6 +1450,11 @@ class AsyncCampaignResource(AsyncAPIResource):
1432
1450
  """Campaign installation (`CampaignInstallation`) — the Program Editor's Installation tab."""
1433
1451
  return AsyncInstallationResource(self._client)
1434
1452
 
1453
+ @cached_property
1454
+ def custom_domain(self) -> AsyncCustomDomainResource:
1455
+ """Campaign custom domain (`CampaignCustomDomain`) — the domain that serves a program's landing pages."""
1456
+ return AsyncCustomDomainResource(self._client)
1457
+
1435
1458
  @cached_property
1436
1459
  def with_raw_response(self) -> AsyncCampaignResourceWithRawResponse:
1437
1460
  """
@@ -1455,8 +1478,8 @@ class AsyncCampaignResource(AsyncAPIResource):
1455
1478
  self,
1456
1479
  *,
1457
1480
  type: Literal["REFERRAL", "AFFILIATE"],
1458
- company_logo_image_url: str | Omit = omit,
1459
- company_name: str | Omit = omit,
1481
+ company_logo_image_url: Optional[str] | Omit = omit,
1482
+ company_name: Optional[str] | Omit = omit,
1460
1483
  currency_iso: str | Omit = omit,
1461
1484
  goal: Literal[
1462
1485
  "CUSTOMERS",
@@ -1564,8 +1587,8 @@ class AsyncCampaignResource(AsyncAPIResource):
1564
1587
  self,
1565
1588
  id: str,
1566
1589
  *,
1567
- company_logo_image_url: str | Omit = omit,
1568
- company_name: str | Omit = omit,
1590
+ company_logo_image_url: Optional[str] | Omit = omit,
1591
+ company_name: Optional[str] | Omit = omit,
1569
1592
  name: str | Omit = omit,
1570
1593
  status: Literal["IN_PROGRESS", "COMPLETE"] | Omit = omit,
1571
1594
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -1582,8 +1605,8 @@ class AsyncCampaignResource(AsyncAPIResource):
1582
1605
  dedicated config sub-resources, not here. The program cannot be deleted via this
1583
1606
  endpoint.
1584
1607
  Changes to participant email content are checked before saving. Rejected content returns
1585
- `400`; if the check is unavailable, `503` asks you to retry. Neither response saves the
1586
- change. A concurrent edit can return `409`; reload the program before retrying.
1608
+ `400` and is not saved. A concurrent edit can return `409`; reload the program before
1609
+ retrying.
1587
1610
 
1588
1611
  Args:
1589
1612
  status: The requested program status. `IN_PROGRESS` publishes or resumes the program;
@@ -1684,6 +1707,7 @@ class AsyncCampaignResource(AsyncAPIResource):
1684
1707
  metadata: Dict[str, object] | Omit = omit,
1685
1708
  mobile_instance_id: str | Omit = omit,
1686
1709
  referral_status: Literal["CREDIT_PENDING", "CREDIT_AWARDED"] | Omit = omit,
1710
+ referred_at: Optional[int] | Omit = omit,
1687
1711
  referred_by: str | Omit = omit,
1688
1712
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
1689
1713
  # The extra values given here take precedence over values defined on the client or passed to this method.
@@ -1707,8 +1731,14 @@ class AsyncCampaignResource(AsyncAPIResource):
1707
1731
 
1708
1732
  is_affiliate: Affiliate programs only. Controls affiliate enrollment for a new participant.
1709
1733
 
1710
- language: The language of the participant's portal and program emails. Must be one of the
1711
- program's languages. Applied only when this request creates the participant.
1734
+ language: The language of the participant's portal and program emails. Stored when it is one of
1735
+ the program's languages. A regional tag maps to its language (for example, `es-MX` is
1736
+ stored as `es`). Any other value is ignored and the program's base language applies.
1737
+ Applied only when this request creates the participant.
1738
+
1739
+ referred_at: When the participant was referred, in Unix milliseconds. Used only with a valid
1740
+ `referredBy`. If you omit `referralStatus`, GrowSurf compares this time with the
1741
+ program's referral credit window to set it. Defaults to the time of the request.
1712
1742
 
1713
1743
  referred_by: Referrer participant ID or email address.
1714
1744
 
@@ -1736,6 +1766,7 @@ class AsyncCampaignResource(AsyncAPIResource):
1736
1766
  "metadata": metadata,
1737
1767
  "mobile_instance_id": mobile_instance_id,
1738
1768
  "referral_status": referral_status,
1769
+ "referred_at": referred_at,
1739
1770
  "referred_by": referred_by,
1740
1771
  },
1741
1772
  campaign_create_mobile_participant_token_params.CampaignCreateMobileParticipantTokenParams,
@@ -2028,10 +2059,7 @@ class AsyncCampaignResource(AsyncAPIResource):
2028
2059
  next_id: str | Omit = omit,
2029
2060
  offset: int | Omit = omit,
2030
2061
  referral_status: ReferralStatus | Omit = omit,
2031
- sort_by: Literal[
2032
- "updatedAt", "createdAt", "email", "firstName", "lastName", "referralStatus", "referralTriggeredAt"
2033
- ]
2034
- | Omit = omit,
2062
+ sort_by: Literal["updatedAt", "createdAt", "email", "referralTriggeredAt"] | Omit = omit,
2035
2063
  # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
2036
2064
  # The extra values given here take precedence over values defined on the client or passed to this method.
2037
2065
  extra_headers: Headers | None = None,
@@ -2734,6 +2762,11 @@ class CampaignResourceWithRawResponse:
2734
2762
  """Campaign installation (`CampaignInstallation`) — the Program Editor's Installation tab."""
2735
2763
  return InstallationResourceWithRawResponse(self._campaign.installation)
2736
2764
 
2765
+ @cached_property
2766
+ def custom_domain(self) -> CustomDomainResourceWithRawResponse:
2767
+ """Campaign custom domain (`CampaignCustomDomain`) — the domain that serves a program's landing pages."""
2768
+ return CustomDomainResourceWithRawResponse(self._campaign.custom_domain)
2769
+
2737
2770
 
2738
2771
  class AsyncCampaignResourceWithRawResponse:
2739
2772
  def __init__(self, campaign: AsyncCampaignResource) -> None:
@@ -2856,6 +2889,11 @@ class AsyncCampaignResourceWithRawResponse:
2856
2889
  """Campaign installation (`CampaignInstallation`) — the Program Editor's Installation tab."""
2857
2890
  return AsyncInstallationResourceWithRawResponse(self._campaign.installation)
2858
2891
 
2892
+ @cached_property
2893
+ def custom_domain(self) -> AsyncCustomDomainResourceWithRawResponse:
2894
+ """Campaign custom domain (`CampaignCustomDomain`) — the domain that serves a program's landing pages."""
2895
+ return AsyncCustomDomainResourceWithRawResponse(self._campaign.custom_domain)
2896
+
2859
2897
 
2860
2898
  class CampaignResourceWithStreamingResponse:
2861
2899
  def __init__(self, campaign: CampaignResource) -> None:
@@ -2978,6 +3016,11 @@ class CampaignResourceWithStreamingResponse:
2978
3016
  """Campaign installation (`CampaignInstallation`) — the Program Editor's Installation tab."""
2979
3017
  return InstallationResourceWithStreamingResponse(self._campaign.installation)
2980
3018
 
3019
+ @cached_property
3020
+ def custom_domain(self) -> CustomDomainResourceWithStreamingResponse:
3021
+ """Campaign custom domain (`CampaignCustomDomain`) — the domain that serves a program's landing pages."""
3022
+ return CustomDomainResourceWithStreamingResponse(self._campaign.custom_domain)
3023
+
2981
3024
 
2982
3025
  class AsyncCampaignResourceWithStreamingResponse:
2983
3026
  def __init__(self, campaign: AsyncCampaignResource) -> None:
@@ -3099,3 +3142,8 @@ class AsyncCampaignResourceWithStreamingResponse:
3099
3142
  def installation(self) -> AsyncInstallationResourceWithStreamingResponse:
3100
3143
  """Campaign installation (`CampaignInstallation`) — the Program Editor's Installation tab."""
3101
3144
  return AsyncInstallationResourceWithStreamingResponse(self._campaign.installation)
3145
+
3146
+ @cached_property
3147
+ def custom_domain(self) -> AsyncCustomDomainResourceWithStreamingResponse:
3148
+ """Campaign custom domain (`CampaignCustomDomain`) — the domain that serves a program's landing pages."""
3149
+ return AsyncCustomDomainResourceWithStreamingResponse(self._campaign.custom_domain)