notion-ruby-client 0.0.7 → 1.0.0.pre.beta1

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/Dockerfile +5 -0
  3. data/.devcontainer/boot.sh +1 -0
  4. data/.devcontainer/devcontainer.json +30 -0
  5. data/.github/workflows/ci.yml +1 -0
  6. data/.gitignore +7 -0
  7. data/.rubocop.yml +9 -0
  8. data/CHANGELOG.md +42 -0
  9. data/CONTRIBUTING.md +51 -0
  10. data/Gemfile.lock +39 -12
  11. data/README.md +377 -79
  12. data/bin/console +31 -0
  13. data/lib/notion/api/endpoints/blocks.rb +51 -7
  14. data/lib/notion/api/endpoints/databases.rb +60 -31
  15. data/lib/notion/api/endpoints/pages.rb +25 -8
  16. data/lib/notion/api/endpoints/search.rb +41 -0
  17. data/lib/notion/api/endpoints/users.rb +14 -3
  18. data/lib/notion/api/endpoints.rb +3 -1
  19. data/lib/notion/api/errors/too_many_requests.rb +15 -0
  20. data/lib/notion/api/errors.rb +0 -2
  21. data/lib/notion/config.rb +2 -0
  22. data/lib/notion/pagination/cursor.rb +5 -2
  23. data/lib/notion/version.rb +2 -2
  24. data/lib/notion-ruby-client.rb +2 -0
  25. data/notion-ruby-client.gemspec +4 -2
  26. data/spec/fixtures/notion/block.yml +146 -0
  27. data/spec/fixtures/notion/block_append_children.yml +76 -62
  28. data/spec/fixtures/notion/block_children.yml +80 -65
  29. data/spec/fixtures/notion/create_database.yml +149 -0
  30. data/spec/fixtures/notion/create_page.yml +76 -61
  31. data/spec/fixtures/notion/database.yml +78 -61
  32. data/spec/fixtures/notion/database_query.yml +81 -62
  33. data/spec/fixtures/notion/delete_block.yml +145 -0
  34. data/spec/fixtures/notion/page.yml +78 -61
  35. data/spec/fixtures/notion/page_property_item.yml +143 -0
  36. data/spec/fixtures/notion/paginated_block_children.yml +296 -242
  37. data/spec/fixtures/notion/paginated_database_query.yml +79 -62
  38. data/spec/fixtures/notion/paginated_databases_list.yml +78 -61
  39. data/spec/fixtures/notion/paginated_search.yml +301 -0
  40. data/spec/fixtures/notion/paginated_users_list.yml +143 -130
  41. data/spec/fixtures/notion/search.yml +160 -0
  42. data/spec/fixtures/notion/search_with_query.yml +152 -0
  43. data/spec/fixtures/notion/update_block.yml +148 -0
  44. data/spec/fixtures/notion/update_database.yml +152 -0
  45. data/spec/fixtures/notion/update_page.yml +79 -63
  46. data/spec/fixtures/notion/users.yml +69 -56
  47. data/spec/fixtures/notion/users_list.yml +143 -130
  48. data/spec/fixtures/notion/users_me.yml +144 -0
  49. data/spec/notion/api/endpoints/blocks_spec.rb +44 -12
  50. data/spec/notion/api/endpoints/databases_spec.rb +38 -17
  51. data/spec/notion/api/endpoints/pages_spec.rb +21 -13
  52. data/spec/notion/api/endpoints/search_spec.rb +26 -0
  53. data/spec/notion/api/endpoints/users_spec.rb +9 -4
  54. data/spec/notion/pagination/cursor_spec.rb +126 -0
  55. metadata +73 -19
  56. data/.rspec_status +0 -18
  57. data/notion-ruby-client-0.0.4.gem +0 -0
  58. data/scratchpad.rb +0 -22
  59. data/screenshots/create_notion_bot.png +0 -0
  60. data/spec/fixtures/notion/databases_list.yml +0 -133
@@ -4,6 +4,50 @@ module Notion
4
4
  module Api
5
5
  module Endpoints
6
6
  module Blocks
7
+ #
8
+ # Retrieves a Block object using the ID specified.
9
+ #
10
+ # @option options [id] :block_id
11
+ # Block to get children info on.
12
+ def block(options = {})
13
+ throw ArgumentError.new('Required arguments :block_id missing') if options[:block_id].nil?
14
+ get("blocks/#{options[:block_id]}")
15
+ end
16
+
17
+ #
18
+ # Updates the content for the specified block_id based on
19
+ # the block type. Supported fields based on the block object
20
+ # type (see Block object for available fields and the
21
+ # expected input for each field).
22
+ #
23
+ # @option options [id] :block_id
24
+ # Block to get children info on.
25
+ #
26
+ # @option options [string] {type}
27
+ # The block object type value with the properties to be
28
+ # updated. Currently only text (for supported block types)
29
+ # and checked (for to_do blocks) fields can be updated.
30
+ def update_block(options = {})
31
+ throw ArgumentError.new('Required arguments :block_id missing') if options[:block_id].nil?
32
+ patch("blocks/#{options[:block_id]}", options.except(:block_id))
33
+ end
34
+
35
+ #
36
+ # Sets a Block object, including page blocks, to archived: true
37
+ # using the ID specified. Note: in the Notion UI application, this
38
+ # moves the block to the "Trash" where it can still be accessed and
39
+ # restored.
40
+ #
41
+ # To restore the block with the API, use the Update a block or
42
+ # Update page respectively.
43
+ #
44
+ # @option options [id] :block_id
45
+ # Block to get children info on.
46
+ def delete_block(options = {})
47
+ throw ArgumentError.new('Required arguments :block_id missing') if options[:block_id].nil?
48
+ delete("blocks/#{options[:block_id]}")
49
+ end
50
+
7
51
  #
8
52
  # Returns a paginated array of Block objects contained in the
9
53
  # block of the requested path using the ID specified.
@@ -14,16 +58,16 @@ module Notion
14
58
  #
15
59
  # Returns a 400 or 429 HTTP response if the request exceeds Notion's Request limits.
16
60
  #
17
- # @option options [id] :id
61
+ # @option options [id] :block_id
18
62
  # Block to get children info on.
19
63
  def block_children(options = {})
20
- throw ArgumentError.new('Required arguments :id missing') if options[:id].nil?
64
+ throw ArgumentError.new('Required arguments :block_id missing') if options[:block_id].nil?
21
65
  if block_given?
22
66
  Pagination::Cursor.new(self, :block_children, options).each do |page|
23
67
  yield page
24
68
  end
25
69
  else
26
- get("blocks/#{options[:id]}/children", options)
70
+ get("blocks/#{options[:block_id]}/children", options.except(:block_id))
27
71
  end
28
72
  end
29
73
 
@@ -38,14 +82,14 @@ module Notion
38
82
  #
39
83
  # Returns a 400 or 429 HTTP response if the request exceeds Notion's Request limits.
40
84
  #
41
- # @option options [id] :id
42
- # Block to get children info on.
85
+ # @option options [id] :block_id
86
+ # Block to append children to.
43
87
  #
44
88
  # @option options [[Object]] :children
45
89
  # Children blocks to append
46
90
  def block_append_children(options = {})
47
- throw ArgumentError.new('Required arguments :id missing') if options[:id].nil?
48
- patch("blocks/#{options[:id]}/children", options)
91
+ throw ArgumentError.new('Required arguments :block_id missing') if options[:block_id].nil?
92
+ patch("blocks/#{options[:block_id]}/children", options.except(:block_id))
49
93
  end
50
94
  end
51
95
  end
@@ -4,20 +4,6 @@ module Notion
4
4
  module Api
5
5
  module Endpoints
6
6
  module Databases
7
- #
8
- # Retrieves a Database object using the ID specified in the request.
9
- #
10
- # Returns a 404 HTTP response if the database doesn't exist, or if the bot
11
- # doesn't have access to the database. Returns a 429 HTTP response if the
12
- # request exceeds Notion's Request limits.
13
- #
14
- # @option options [id] :id
15
- # Database to get info on.
16
- def database(options = {})
17
- throw ArgumentError.new('Required arguments :id missing') if options[:id].nil?
18
- get("databases/#{options[:id]}")
19
- end
20
-
21
7
  #
22
8
  # Gets a paginated array of Page object s contained in the requested database,
23
9
  # filtered and ordered according to the filter and sort objects provided in the request.
@@ -30,7 +16,7 @@ module Notion
30
16
  # database properties and can be combined. The order of the sorts in the request
31
17
  # matter, with earlier sorts taking precedence over later ones.
32
18
  #
33
- # @option options [id] :id
19
+ # @option options [id] :database_id
34
20
  # Database to query.
35
21
  #
36
22
  # @option options [Object] :filter
@@ -44,33 +30,76 @@ module Notion
44
30
  # to a start_cursor attribute returned by a previous request's next_cursor.
45
31
  # Default value fetches the first "page" of the collection.
46
32
  # See pagination for more detail.
33
+ #
34
+ # @option options [integer] :page_size
35
+ # The number of items from the full list desired in the response. Maximum: 100
47
36
  def database_query(options = {})
48
- throw ArgumentError.new('Required arguments :id missing') if options[:id].nil?
37
+ throw ArgumentError.new('Required arguments :database_id missing') if options[:database_id].nil?
49
38
  if block_given?
50
39
  Pagination::Cursor.new(self, :database_query, options).each do |page|
51
40
  yield page
52
41
  end
53
42
  else
54
- post("databases/#{options[:id]}/query", options)
43
+ post("databases/#{options[:database_id]}/query", options.except(:database_id))
55
44
  end
56
45
  end
57
46
 
58
47
  #
59
- # Returns a paginated list of Databases objects for the workspace.
48
+ # Creates a new database in the specified page.
60
49
  #
61
- # @option options [UUID] :start_cursor
62
- # Paginate through collections of data by setting the cursor parameter
63
- # to a start_cursor attribute returned by a previous request's next_cursor.
64
- # Default value fetches the first "page" of the collection.
65
- # See pagination for more detail.
66
- def databases_list(options = {})
67
- if block_given?
68
- Pagination::Cursor.new(self, :databases_list, options).each do |page|
69
- yield page
70
- end
71
- else
72
- get('databases', options)
73
- end
50
+ # @option options [Object] :parent
51
+ # Parent of the database, which is always going to be a page.
52
+ #
53
+ # @option options [Object] :title
54
+ # Title of this database.
55
+ #
56
+ # @option options [Object] :properties
57
+ # Property schema of database.
58
+ # The keys are the names of properties as they appear in Notion and the values are
59
+ # property schema objects. Property Schema Object is a metadata that controls
60
+ # how a database property behaves, e.g. {"checkbox": {}}.
61
+ # Each database must have exactly one database property schema object of type "title".
62
+ def create_database(options = {})
63
+ throw ArgumentError.new('Required arguments :parent.page_id missing') if options.dig(:parent, :page_id).nil?
64
+ throw ArgumentError.new('Required arguments :title missing') if options.dig(:title).nil?
65
+ throw ArgumentError.new('Required arguments :properties missing') if options.dig(:properties).nil?
66
+ post('databases', options)
67
+ end
68
+
69
+ #
70
+ # Updates an existing database as specified by the parameters.
71
+ #
72
+ # @option options [id] :database_id
73
+ # Database to update.
74
+ #
75
+ # @option options [Object] :title
76
+ # Title of database as it appears in Notion. An array of rich text objects.
77
+ # If omitted, the database title will remain unchanged.
78
+ #
79
+ # @option options [Object] :properties
80
+ # Updates to the property schema of a database.
81
+ # If updating an existing property, the keys are the names or IDs
82
+ # of the properties as they appear in Notion and the values
83
+ # are property schema objects. If adding a new property, the key is
84
+ # the name of the database property and the value is a property schema object.
85
+ #
86
+ def update_database(options = {})
87
+ throw ArgumentError.new('Required arguments :database_id missing') if options.dig(:database_id).nil?
88
+ patch("databases/#{options[:database_id]}", options.except(:database_id))
89
+ end
90
+
91
+ #
92
+ # Retrieves a Database object using the ID specified in the request.
93
+ #
94
+ # Returns a 404 HTTP response if the database doesn't exist, or if the bot
95
+ # doesn't have access to the database. Returns a 429 HTTP response if the
96
+ # request exceeds Notion's Request limits.
97
+ #
98
+ # @option options [id] :database_id
99
+ # Database to get info on.
100
+ def database(options = {})
101
+ throw ArgumentError.new('Required arguments :database_id missing') if options[:database_id].nil?
102
+ get("databases/#{options[:database_id]}")
74
103
  end
75
104
  end
76
105
  end
@@ -8,15 +8,15 @@ module Notion
8
8
  # Retrieves a 📄Page object using the ID specified in the request path.
9
9
  # Note that this version of the API only exposes page properties, not page content
10
10
  #
11
- # @option options [id] :id
11
+ # @option options [id] :page_id
12
12
  # Page to get info on.
13
13
  #
14
14
  # @option options [bool] :archived
15
15
  # Set to true to retrieve an archived page; must be false or omitted to
16
16
  # retrieve a page that has not been archived. Defaults to false.
17
17
  def page(options = {})
18
- throw ArgumentError.new('Required arguments :id missing') if options[:id].nil?
19
- get("pages/#{options[:id]}")
18
+ throw ArgumentError.new('Required argument :page_id missing') if options[:page_id].nil?
19
+ get("pages/#{options[:page_id]}")
20
20
  end
21
21
 
22
22
  #
@@ -36,9 +36,9 @@ module Notion
36
36
  # specific to the property type, e.g. {"checkbox": true}.
37
37
  #
38
38
  # @option options [Object] :children
39
- # An optional array of Block objects representing the Page’s conent
39
+ # An optional array of Block objects representing the Page’s content
40
40
  def create_page(options = {})
41
- throw ArgumentError.new('Required arguments :parent.database_id missing') if options.dig(:parent, :database_id).nil?
41
+ throw ArgumentError.new('Required argument :parent.database_id missing') if options.dig(:parent, :database_id).nil?
42
42
  post("pages", options)
43
43
  end
44
44
 
@@ -50,7 +50,7 @@ module Notion
50
50
  # Note that this iteration of the API will only expose page properties, not page
51
51
  # content, as described in the data model.
52
52
  #
53
- # @option options [id] :id
53
+ # @option options [id] :page_id
54
54
  # Page to get info on.
55
55
  #
56
56
  # @option options [Object] :properties
@@ -60,8 +60,25 @@ module Notion
60
60
  # appears in Notion, or property ID. value object Object containing a value
61
61
  # specific to the property type, e.g. {"checkbox": true}.
62
62
  def update_page(options = {})
63
- throw ArgumentError.new('Required arguments :id missing') if options[:id].nil?
64
- patch("pages/#{options[:id]}", options)
63
+ throw ArgumentError.new('Required argument :page_id missing') if options[:page_id].nil?
64
+ patch("pages/#{options[:page_id]}", options.except(:page_id))
65
+ end
66
+
67
+ #
68
+ # Retrieves a `property_item` object for a given `page_id` and `property_id`.
69
+ # Depending on the property type, the object returned will either be a value
70
+ # or a paginated list of property item values.
71
+ #
72
+ # @option options [id] :page_id
73
+ # Page to get info on.
74
+ #
75
+ # @option options [id] :property_id
76
+ # Property to get info on.
77
+ #
78
+ def page_property_item(options = {})
79
+ throw ArgumentError.new('Required argument :page_id missing') if options[:page_id].nil?
80
+ throw ArgumentError.new('Required argument :property_id missing') if options[:property_id].nil?
81
+ get("pages/#{options[:page_id]}/properties/#{options[:property_id]}")
65
82
  end
66
83
  end
67
84
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Notion
4
+ module Api
5
+ module Endpoints
6
+ module Search
7
+ #
8
+ # Searches all pages and child pages that are shared with the integration.
9
+ # The results may include databases.
10
+ #
11
+ # @option options [string] :query
12
+ # When supplied, limits which pages are returned by comparing the query to the page title.
13
+ #
14
+ # @option options [Object] :filter
15
+ # When supplied, filters the results based on the provided criteria.
16
+ #
17
+ # @option options [[Object]] :sorts
18
+ # When supplied, sorts the results based on the provided criteria.
19
+ # Limitation: Currently only a single sort is allowed and is limited to last_edited_time.
20
+ #
21
+ # @option options [UUID] :start_cursor
22
+ # Paginate through collections of data by setting the cursor parameter
23
+ # to a start_cursor attribute returned by a previous request's next_cursor.
24
+ # Default value fetches the first "page" of the collection.
25
+ # See pagination for more detail.
26
+ #
27
+ # @option options [integer] :page_size
28
+ # The number of items from the full list desired in the response. Maximum: 100
29
+ def search(options = {})
30
+ if block_given?
31
+ Pagination::Cursor.new(self, :search, options).each do |page|
32
+ yield page
33
+ end
34
+ else
35
+ post('search', options)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -4,14 +4,22 @@ module Notion
4
4
  module Api
5
5
  module Endpoints
6
6
  module Users
7
+ #
8
+ # Retrieves the bot User associated with the API token provided in
9
+ # the authorization header. The bot will have an `owner` field with
10
+ # information about the person who authorized the integration.
11
+ def me
12
+ get("users/me")
13
+ end
14
+
7
15
  #
8
16
  # Retrieves a User object using the ID specified in the request.
9
17
  #
10
- # @option options [id] :id
18
+ # @option options [id] :user_id
11
19
  # User to get info on.
12
20
  def user(options = {})
13
- throw ArgumentError.new('Required arguments :id missing') if options[:id].nil?
14
- get("users/#{options[:id]}")
21
+ throw ArgumentError.new('Required arguments :user_id missing') if options[:user_id].nil?
22
+ get("users/#{options[:user_id]}")
15
23
  end
16
24
 
17
25
  #
@@ -22,6 +30,9 @@ module Notion
22
30
  # to a start_cursor attribute returned by a previous request's next_cursor.
23
31
  # Default value fetches the first "page" of the collection.
24
32
  # See pagination for more detail.
33
+ #
34
+ # @option options [integer] :page_size
35
+ # The number of items from the full list desired in the response. Maximum: 100
25
36
  def users_list(options = {})
26
37
  if block_given?
27
38
  Pagination::Cursor.new(self, :users_list, options).each do |page|
@@ -4,6 +4,7 @@ require_relative 'endpoints/blocks'
4
4
  require_relative 'endpoints/databases'
5
5
  require_relative 'endpoints/pages'
6
6
  require_relative 'endpoints/users'
7
+ require_relative 'endpoints/search'
7
8
 
8
9
  module Notion
9
10
  module Api
@@ -12,6 +13,7 @@ module Notion
12
13
  include Databases
13
14
  include Pages
14
15
  include Users
16
+ include Search
15
17
  end
16
18
  end
17
- end
19
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ module Notion
3
+ module Api
4
+ module Errors
5
+ class TooManyRequests < ::Faraday::Error
6
+ attr_reader :response
7
+
8
+ def initialize(response)
9
+ @response = response
10
+ super 'Too many requests'
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -8,7 +8,6 @@ module Notion
8
8
  class InternalError < NotionError; end
9
9
  class InvalidRequest < NotionError; end
10
10
  class ObjectNotFound < NotionError; end
11
- class TooManyRequests < NotionError; end
12
11
  class Unauthorized < NotionError; end
13
12
 
14
13
  ERROR_CLASSES = {
@@ -17,7 +16,6 @@ module Notion
17
16
  'internal_error' => InternalError,
18
17
  'invalid_request' => InvalidRequest,
19
18
  'object_not_found' => ObjectNotFound,
20
- 'rate_limited' => TooManyRequests,
21
19
  'unauthorized' => Unauthorized
22
20
  }.freeze
23
21
  end
data/lib/notion/config.rb CHANGED
@@ -15,6 +15,7 @@ module Notion
15
15
  open_timeout
16
16
  default_page_size
17
17
  default_max_retries
18
+ default_retry_after
18
19
  adapter
19
20
  ].freeze
20
21
 
@@ -32,6 +33,7 @@ module Notion
32
33
  self.open_timeout = nil
33
34
  self.default_page_size = 100
34
35
  self.default_max_retries = 100
36
+ self.default_retry_after = 10
35
37
  self.adapter = ::Faraday.default_adapter
36
38
  end
37
39
 
@@ -9,6 +9,7 @@ module Notion
9
9
  attr_reader :verb
10
10
  attr_reader :sleep_interval
11
11
  attr_reader :max_retries
12
+ attr_reader :retry_after
12
13
  attr_reader :params
13
14
 
14
15
  def initialize(client, verb, params = {})
@@ -17,13 +18,15 @@ module Notion
17
18
  @params = params.dup
18
19
  @sleep_interval = @params.delete(:sleep_interval)
19
20
  @max_retries = @params.delete(:max_retries) || client.default_max_retries
21
+ @retry_after = @params.delete(:retry_after) || client.default_retry_after
20
22
  end
21
23
 
22
24
  def each
23
25
  next_cursor = nil
24
26
  retry_count = 0
25
27
  loop do
26
- query = next_cursor.nil? ? params : params.merge(start_cursor: next_cursor)
28
+ query = { page_size: client.default_page_size }.merge(params)
29
+ query = query.merge(start_cursor: next_cursor) unless next_cursor.nil?
27
30
  begin
28
31
  response = client.send(verb, query)
29
32
  rescue Notion::Api::Errors::TooManyRequests => e
@@ -31,7 +34,7 @@ module Notion
31
34
 
32
35
  client.logger.debug("#{self.class}##{__method__}") { e.to_s }
33
36
  retry_count += 1
34
- sleep(e.retry_after)
37
+ sleep(retry_after)
35
38
  next
36
39
  end
37
40
  yield response
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module Notion
3
- VERSION = '0.0.7'
4
- NOTION_REQUEST_VERSION = '2021-05-11'
3
+ VERSION = '1.0.0-beta1'
4
+ NOTION_REQUEST_VERSION = '2022-02-22'
5
5
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ require 'active_support/core_ext/hash/except'
2
3
  require 'faraday'
3
4
  require 'faraday_middleware'
4
5
  require 'json'
@@ -17,6 +18,7 @@ require_relative 'notion/api/errors/notion_error'
17
18
  require_relative 'notion/api/error'
18
19
  require_relative 'notion/api/errors'
19
20
  require_relative 'notion/api/errors/internal_error'
21
+ require_relative 'notion/api/errors/too_many_requests'
20
22
  require_relative 'notion/faraday/response/raise_error'
21
23
  require_relative 'notion/faraday/response/wrap_error'
22
24
  require_relative 'notion/faraday/connection'
@@ -15,10 +15,12 @@ Gem::Specification.new do |s|
15
15
  s.homepage = 'http://github.com/orbit-love/notion-ruby-client'
16
16
  s.licenses = ['MIT']
17
17
  s.summary = 'Notion API client for Ruby.'
18
+ s.add_dependency 'activesupport', '~> 6'
19
+ s.add_dependency 'dotenv'
18
20
  s.add_dependency 'faraday', '>= 1.0'
19
21
  s.add_dependency 'faraday_middleware'
20
- s.add_dependency 'hashie'
21
- s.add_development_dependency 'rake', '~> 10'
22
+ s.add_dependency 'hashie', '~> 5'
23
+ s.add_development_dependency 'rake', '~> 13'
22
24
  s.add_development_dependency 'rspec'
23
25
  s.add_development_dependency 'rubocop', '~> 0.82.0'
24
26
  s.add_development_dependency 'rubocop-performance', '~> 1.5.2'
@@ -0,0 +1,146 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.notion.com/v1/blocks/32af3324-ba02-4516-ae88-5728a4d569f4
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/json; charset=utf-8
12
+ User-Agent:
13
+ - Notion Ruby Client/0.0.8
14
+ Authorization:
15
+ - Bearer <NOTION_API_TOKEN>
16
+ Notion-Version:
17
+ - '2022-02-22'
18
+ Accept-Encoding:
19
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Date:
26
+ - Sun, 29 Aug 2021 17:45:01 GMT
27
+ Content-Type:
28
+ - application/json; charset=utf-8
29
+ Transfer-Encoding:
30
+ - chunked
31
+ Connection:
32
+ - keep-alive
33
+ X-Dns-Prefetch-Control:
34
+ - 'off'
35
+ X-Frame-Options:
36
+ - SAMEORIGIN
37
+ Strict-Transport-Security:
38
+ - max-age=5184000; includeSubDomains
39
+ X-Download-Options:
40
+ - noopen
41
+ X-Content-Type-Options:
42
+ - nosniff
43
+ X-Xss-Protection:
44
+ - 1; mode=block
45
+ Referrer-Policy:
46
+ - same-origin
47
+ Content-Security-Policy:
48
+ - 'script-src ''self'' ''unsafe-inline'' ''unsafe-eval'' https://gist.github.com
49
+ https://apis.google.com https://api.amplitude.com https://widget.intercom.io
50
+ https://js.intercomcdn.com https://logs-01.loggly.com https://cdn.segment.com
51
+ https://analytics.pgncs.notion.so https://o324374.ingest.sentry.io https://checkout.stripe.com
52
+ https://js.stripe.com https://embed.typeform.com https://admin.typeform.com
53
+ https://public.profitwell.com js.sentry-cdn.com https://js.chilipiper.com
54
+ https://platform.twitter.com https://cdn.syndication.twimg.com https://www.googletagmanager.com
55
+ https://x.clearbitjs.com https://client-registry.mutinycdn.com https://client.mutinycdn.com/
56
+ https://user-data.mutinycdn.com; connect-src ''self'' https://msgstore.www.notion.so
57
+ wss://msgstore.www.notion.so ws://localhost:* https://notion-emojis.s3-us-west-2.amazonaws.com
58
+ https://s3-us-west-2.amazonaws.com https://s3.us-west-2.amazonaws.com https://notion-production-snapshots-2.s3.us-west-2.amazonaws.com
59
+ https: http: https://api.amplitude.com https://api.embed.ly https://js.intercomcdn.com
60
+ https://api-iam.intercom.io wss://nexus-websocket-a.intercom.io https://logs-01.loggly.com
61
+ https://cdn.segment.com https://api.segment.io https://analytics.pgncs.notion.so
62
+ https://api.pgncs.notion.so https://o324374.ingest.sentry.io https://checkout.stripe.com
63
+ https://js.stripe.com https://cdn.contentful.com https://preview.contentful.com
64
+ https://images.ctfassets.net https://www2.profitwell.com https://tracking.chilipiper.com
65
+ https://api.chilipiper.com https://api.unsplash.com https://boards-api.greenhouse.io
66
+ https://user-data.mutinycdn.com https://api-v2.mutinyhq.io https://api.statuspage.io
67
+ https://pgncd.notion.so; font-src ''self'' data: https://cdnjs.cloudflare.com
68
+ https://js.intercomcdn.com; img-src ''self'' data: blob: https: https://platform.twitter.com
69
+ https://syndication.twitter.com https://pbs.twimg.com https://ton.twimg.com
70
+ www.googletagmanager.com; style-src ''self'' ''unsafe-inline'' https://cdnjs.cloudflare.com
71
+ https://github.githubassets.com https://js.chilipiper.com https://platform.twitter.com
72
+ https://ton.twimg.com; frame-src https: http:; media-src https: http:'
73
+ X-Content-Security-Policy:
74
+ - 'script-src ''self'' ''unsafe-inline'' ''unsafe-eval'' https://gist.github.com
75
+ https://apis.google.com https://api.amplitude.com https://widget.intercom.io
76
+ https://js.intercomcdn.com https://logs-01.loggly.com https://cdn.segment.com
77
+ https://analytics.pgncs.notion.so https://o324374.ingest.sentry.io https://checkout.stripe.com
78
+ https://js.stripe.com https://embed.typeform.com https://admin.typeform.com
79
+ https://public.profitwell.com js.sentry-cdn.com https://js.chilipiper.com
80
+ https://platform.twitter.com https://cdn.syndication.twimg.com https://www.googletagmanager.com
81
+ https://x.clearbitjs.com https://client-registry.mutinycdn.com https://client.mutinycdn.com/
82
+ https://user-data.mutinycdn.com; connect-src ''self'' https://msgstore.www.notion.so
83
+ wss://msgstore.www.notion.so ws://localhost:* https://notion-emojis.s3-us-west-2.amazonaws.com
84
+ https://s3-us-west-2.amazonaws.com https://s3.us-west-2.amazonaws.com https://notion-production-snapshots-2.s3.us-west-2.amazonaws.com
85
+ https: http: https://api.amplitude.com https://api.embed.ly https://js.intercomcdn.com
86
+ https://api-iam.intercom.io wss://nexus-websocket-a.intercom.io https://logs-01.loggly.com
87
+ https://cdn.segment.com https://api.segment.io https://analytics.pgncs.notion.so
88
+ https://api.pgncs.notion.so https://o324374.ingest.sentry.io https://checkout.stripe.com
89
+ https://js.stripe.com https://cdn.contentful.com https://preview.contentful.com
90
+ https://images.ctfassets.net https://www2.profitwell.com https://tracking.chilipiper.com
91
+ https://api.chilipiper.com https://api.unsplash.com https://boards-api.greenhouse.io
92
+ https://user-data.mutinycdn.com https://api-v2.mutinyhq.io https://api.statuspage.io
93
+ https://pgncd.notion.so; font-src ''self'' data: https://cdnjs.cloudflare.com
94
+ https://js.intercomcdn.com; img-src ''self'' data: blob: https: https://platform.twitter.com
95
+ https://syndication.twitter.com https://pbs.twimg.com https://ton.twimg.com
96
+ www.googletagmanager.com; style-src ''self'' ''unsafe-inline'' https://cdnjs.cloudflare.com
97
+ https://github.githubassets.com https://js.chilipiper.com https://platform.twitter.com
98
+ https://ton.twimg.com; frame-src https: http:; media-src https: http:'
99
+ X-Webkit-Csp:
100
+ - 'script-src ''self'' ''unsafe-inline'' ''unsafe-eval'' https://gist.github.com
101
+ https://apis.google.com https://api.amplitude.com https://widget.intercom.io
102
+ https://js.intercomcdn.com https://logs-01.loggly.com https://cdn.segment.com
103
+ https://analytics.pgncs.notion.so https://o324374.ingest.sentry.io https://checkout.stripe.com
104
+ https://js.stripe.com https://embed.typeform.com https://admin.typeform.com
105
+ https://public.profitwell.com js.sentry-cdn.com https://js.chilipiper.com
106
+ https://platform.twitter.com https://cdn.syndication.twimg.com https://www.googletagmanager.com
107
+ https://x.clearbitjs.com https://client-registry.mutinycdn.com https://client.mutinycdn.com/
108
+ https://user-data.mutinycdn.com; connect-src ''self'' https://msgstore.www.notion.so
109
+ wss://msgstore.www.notion.so ws://localhost:* https://notion-emojis.s3-us-west-2.amazonaws.com
110
+ https://s3-us-west-2.amazonaws.com https://s3.us-west-2.amazonaws.com https://notion-production-snapshots-2.s3.us-west-2.amazonaws.com
111
+ https: http: https://api.amplitude.com https://api.embed.ly https://js.intercomcdn.com
112
+ https://api-iam.intercom.io wss://nexus-websocket-a.intercom.io https://logs-01.loggly.com
113
+ https://cdn.segment.com https://api.segment.io https://analytics.pgncs.notion.so
114
+ https://api.pgncs.notion.so https://o324374.ingest.sentry.io https://checkout.stripe.com
115
+ https://js.stripe.com https://cdn.contentful.com https://preview.contentful.com
116
+ https://images.ctfassets.net https://www2.profitwell.com https://tracking.chilipiper.com
117
+ https://api.chilipiper.com https://api.unsplash.com https://boards-api.greenhouse.io
118
+ https://user-data.mutinycdn.com https://api-v2.mutinyhq.io https://api.statuspage.io
119
+ https://pgncd.notion.so; font-src ''self'' data: https://cdnjs.cloudflare.com
120
+ https://js.intercomcdn.com; img-src ''self'' data: blob: https: https://platform.twitter.com
121
+ https://syndication.twitter.com https://pbs.twimg.com https://ton.twimg.com
122
+ www.googletagmanager.com; style-src ''self'' ''unsafe-inline'' https://cdnjs.cloudflare.com
123
+ https://github.githubassets.com https://js.chilipiper.com https://platform.twitter.com
124
+ https://ton.twimg.com; frame-src https: http:; media-src https: http:'
125
+ Set-Cookie:
126
+ - notion_browser_id=5e3ae42a-9c10-4632-bbd6-f8635f637d51; Domain=www.notion.so;
127
+ Path=/; Expires=Wed, 07 May 2053 19:31:41 GMT; Secure
128
+ Etag:
129
+ - W/"1c9-RV2WR8+djapd2GV8p8VntQ5R7zI"
130
+ Vary:
131
+ - Accept-Encoding
132
+ Cf-Cache-Status:
133
+ - DYNAMIC
134
+ Expect-Ct:
135
+ - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
136
+ Server:
137
+ - cloudflare
138
+ Cf-Ray:
139
+ - 68679732dfea3acb-CDG
140
+ body:
141
+ encoding: UTF-8
142
+ string: '{"object":"block","id":"32af3324-ba02-4516-ae88-5728a4d569f4","created_time":"2021-05-01T17:13:00.000Z","last_edited_time":"2021-08-29T17:18:00.000Z","has_children":true,"type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content":"A
143
+ paragraph with childrens","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"A
144
+ paragraph with childrens","href":null}]}}'
145
+ recorded_at: Sun, 29 Aug 2021 17:45:01 GMT
146
+ recorded_with: VCR 6.0.0