Notion API bằng Python: đọc block tree, data source và cursor
Notion API bằng Python là cách đọc nội dung page, cây block và các dòng trong data source của workspace Notion qua một integration được chia sẻ quyền, thay vì mở trang công khai rồi cào HTML. API yêu cầu token, header Notion-Version và phân trang bằng cursor. ProxyVN đã gọi thật api.notion.com không token và với token giả ngày 29/10/2026 để ghi mã lỗi, rồi dựng server giả lập theo tài liệu chính thức để chạy cây block, cursor, truy vấn data source và retry.
Notion API bằng Python: mục tiêu dữ liệu, quyền và phạm vi truy cập
Trước khi viết code, anh em cần chốt đọc page nào, data source nào và để làm gì. Workspace Notion của một nhóm có thể có hàng nghìn page lồng nhau, mà integration chỉ thấy những page được chia sẻ trực tiếp với nó.
Đọc Notion để làm gì
Nhu cầu hay gặp là sao lưu một khu tài liệu ra file text hoặc Markdown. Nhu cầu thứ hai là đọc một bảng theo dõi, ví dụ danh sách proxy đang dùng kèm ngày gia hạn, để đưa vào báo cáo hay công cụ nhắc việc. Nhu cầu thứ ba là đưa tài liệu vào công cụ tìm kiếm nội bộ.
Cả ba chỉ cần đọc. Bài này không tạo, sửa hay xóa page hay block nào. Khi tạo integration, chỉ bật quyền đọc nội dung là đủ cho các tác vụ trong bài.
Integration chỉ thấy page được chia sẻ
Đây là điểm khác lớn nhất so với nhiều API khác. Có token chưa đủ. Mỗi page hay data source phải được chia sẻ với integration, tài liệu mới của Notion gọi là connection, thì API mới đọc được. Page con kế thừa quyền từ page cha đã chia sẻ.
Theo tài liệu, khi page chưa được chia sẻ, API trả 404 với mã object_not_found, kèm lời nhắc kiểm tra page và database đã chia sẻ với connection chưa. Server giả lập của lab mô phỏng đúng lời nhắc này cho một page con không được chia sẻ.
Lỗi 404 object_not_found với Notion thường là chưa chia sẻ page, không phải sai ID.
Page công khai không có nghĩa là có quyền API
Một page Notion được bật chia sẻ lên web vẫn không đọc được qua API nếu không có token. Lab gọi thử điểm cuối page với một ID dạng page công khai mà không có header Authorization. Kết quả là 401 unauthorized, thông báo header Authorization phải có dạng Bearer kèm token.
Quyền xem trên web và quyền API là hai hệ khác nhau. Muốn đọc qua API, chủ workspace phải tạo integration và chia sẻ page với nó. Không có đường tắt từ link công khai sang API.
Khác bài Confluence và Google Drive
Confluence trả trang với body storage hoặc ADF trong một lần gọi. Notion trả page và nội dung tách riêng: page chỉ có thuộc tính, nội dung là cây block phải gọi từng tầng. Bài Google Drive proxy nói về đồng bộ file qua ứng dụng máy tính, một bài toán khác hẳn.
Bài cũng không bàn việc cào trang Notion công khai. Bài web scraping proxy là gì nói về thu thập trang web không có API. Với Notion của chính mình, API là đường đúng.
Phần chạy thật và phần giả lập
Lab không có workspace Notion để thử, và không tạo tài khoản mới. Phần chạy thật là các request tới api.notion.com không token, với token giả và với các giá trị Notion-Version khác nhau, để ghi mã trạng thái, mã lỗi và header.
Cây block, cursor, truy vấn data source và retry chạy trên server giả lập ở cổng 9740, dựng theo cấu trúc phản hồi trong tài liệu chính thức. Một số mã lỗi của server giả lập do lab tự đặt, các chỗ đó đều được ghi rõ trong bài.
Đầu ra của bài này
Bài hướng tới ba đầu ra. Thứ nhất là export cây block của một page có cursor ở mọi tầng. Thứ hai là bảng phẳng các dòng của data source, giữ nguyên giá trị null. Thứ ba là một bước kiểm tra phiên bản header trước khi chạy. File xuất ghi block ID, loại block, độ sâu và text.
Notion API bằng Python: đọc page/block hoặc data source được chia sẻ với integration theo phiên bản API hiện hành

Chia sẻ với connection
Phần này giải thích phiên bản API, cấu trúc block và khái niệm data source.
Header Notion-Version
Mọi request phải có header Notion-Version. Trang tài liệu phiên bản của Notion ghi phiên bản mới nhất lúc lab đọc là 2026-03-11, trước đó là 2025-09-03. Trang này cũng ghi SDK JavaScript đã bỏ hỗ trợ 2022-06-28 và cũ hơn.
Lab gửi Notion-Version lần lượt là rỗng, 2022-06-28, 2025-09-03, 2026-03-11 và 1999-01-01 tới /v1/users/me không kèm token. Cả năm lần đều trả 401 với cùng thông báo về header Authorization. Máy chủ kiểm tra xác thực trước, nên không thể dùng request không token để biết phiên bản có hợp lệ không.
Phiên bản đổi gì
Hướng dẫn nâng cấp 2025-09-03 đưa vào khái niệm data source: một database có thể chứa nhiều data source, và các điểm cuối truy vấn database chuyển sang truy vấn data source. Code cũ gọi truy vấn database sẽ cần sửa.
Hướng dẫn nâng cấp 2026-03-11 ghi ba thay đổi không tương thích: tham số after khi thêm block con đổi thành position, trường archived đổi thành in_trash, và loại block transcription đổi tên thành meeting_notes. Code chỉ đọc chủ yếu bị ảnh hưởng ở trường in_trash.
Cố định phiên bản trong code
Ghi Notion-Version cố định trong code, ví dụ 2026-03-11, và chỉ đổi sau khi đọc hướng dẫn nâng cấp. Không lấy phiên bản động từ đâu đó, vì một lần đổi phiên bản có thể đổi tên trường mà code đang đọc.
Server giả lập của lab trả 400 với mã missing_version khi thiếu header. Mã này do lab đặt để kiểm tra nhánh xử lý lỗi. Lab chưa xác nhận Notion thật trả mã gì khi token hợp lệ mà thiếu header phiên bản.
Page, block và cây nội dung
Page có thuộc tính như tiêu đề. Nội dung của page là danh sách block con. Mỗi block có id, type, has_children, in_trash và một đối tượng mang tên đúng bằng type, ví dụ paragraph chứa rich_text.
Block có has_children là true thì phải gọi tiếp điểm cuối block children của chính block đó. Một toggle chứa đoạn văn, một gạch đầu dòng chứa gạch đầu dòng con, tất cả là tầng sâu hơn. Trang Retrieve block children mô tả điểm cuối này.
rich_text và plain_text
Text trong block không phải chuỗi đơn mà là mảng rich_text. Mỗi phần tử có plain_text, text.content và annotations như đậm, nghiêng, mã. Muốn có text thuần, nối plain_text của mọi phần tử.
Lab ghép plain_text cho từng block trong cây giả lập. Block code trả "requests.get(url, proxies=px)", gạch đầu dòng trả "Ma hoa ky tu @ thanh %40". Định dạng đậm, nghiêng bị bỏ ở bước này, nếu cần Markdown thì đọc thêm annotations.
Data source thay cho database
Database trong Notion giờ là vỏ chứa, dữ liệu dạng bảng nằm trong data source. Mỗi dòng của data source là một page có properties. Truy vấn dòng dùng POST /v1/data_sources/{id}/query với bộ lọc và sắp xếp trong thân request.
Server giả lập trả 400 với mã invalid_request_url khi gọi điểm cuối truy vấn database kiểu cũ. Mã này do lab đặt để nhắc việc đổi điểm cuối, không phải phản hồi đã kiểm chứng từ Notion thật.
Chuẩn bị truy vấn, page ID, token và phiên bản cho Notion API bằng Python
Phần này đi qua cách lấy ID, cách gửi token và các mã lỗi thật đã ghi được.
Lấy page ID
Page ID là chuỗi 32 ký tự hex, thường thấy ở cuối URL page, có hoặc không có dấu gạch ngang. API chấp nhận cả hai dạng. Data source ID lấy từ phản hồi của điểm cuối database hoặc từ giao diện, không đoán từ URL.
Lưu ID trong file cấu hình, không lưu URL. Tài liệu phiên bản của Notion ghi rõ đường dẫn mà Notion tạo ra cho người mở, có thể đổi tên miền và định dạng. ID mới là định danh ổn định.
Gửi token
Token gửi trong header Authorization dạng Bearer. Token của internal connection mới có tiền tố ntn_. Đọc token từ biến môi trường, không ghi vào file mã.
import os, requests
S = requests.Session()
S.headers.update({"Authorization": f"Bearer {os.environ['NOTION_TOKEN']}",
"Notion-Version": "2026-03-11"})
r = S.get(f"https://api.notion.com/v1/blocks/{PAGE_ID}/children", params={"page_size": 100}, timeout=30)
Đoạn mã trên chưa chạy với token thật.
Hai thông báo 401 khác nhau
Lab ghi được hai thông báo 401 khác nhau. Không có header Authorization, thông báo là header phải có dạng Bearer kèm token. Có header với token giả, thông báo là "API token is invalid." kèm additional_data.reason là token_invalid.
Phân biệt hai thông báo giúp chẩn đoán nhanh. Thông báo thứ nhất nghĩa là code không gửi header, thường do biến môi trường rỗng. Thông báo thứ hai nghĩa là có gửi nhưng token sai hoặc đã bị thu hồi.
Token giả thiếu phiên bản vẫn là 401
Lab gửi token giả mà không có Notion-Version. Kết quả vẫn là 401 token_invalid. Gửi token giả với Notion-Version 1999-01-01 cũng 401. Máy chủ từ chối token trước khi xét phiên bản.
Mọi phản hồi lỗi có header x-notion-request-id và trường request_id trong thân. Ghi giá trị này vào log để khi cần hỏi bộ phận hỗ trợ, họ tra được đúng request.
Điểm cuối data source cũng kiểm tra token trước
Lab gửi POST /v1/data_sources/{id}/query với ID toàn số 0 và token giả. Kết quả là 401 token_invalid, không phải 404. Lab gọi block children với ID toàn số 0 cũng nhận 401. Không có token hợp lệ thì không thể thăm dò ID nào tồn tại.
Giới hạn request theo gói
Trang giới hạn request của Notion ghi mỗi connection có ngân sách request trong khung 60 giây theo gói workspace. Gói Business và Enterprise là 600 request mỗi phút, các gói còn lại là 180 request mỗi phút, tức trung bình 3 request mỗi giây.
Tài liệu ghi truy vấn data source có giới hạn riêng khoảng 3 request mỗi giây cho mỗi connection. Vượt giới hạn trả 429 với mã rate_limited, kèm Retry-After. Với giới hạn theo cửa sổ 60 giây, Retry-After tối đa 60 giây.
Kiểm tra trước khi chạy lô
Trước khi đọc cả khu tài liệu, script nên gọi /v1/users/me một lần. Phản hồi 200 xác nhận token và phiên bản hợp lệ. Phản hồi 401 cho biết ngay token có vấn đề, và thông báo lỗi cho biết là thiếu header hay token sai.
Sau đó gọi block children của page gốc với page_size 1. Phản hồi 200 xác nhận page đã chia sẻ. Phản hồi 404 object_not_found nghĩa là cần nhờ chủ page thêm connection trước khi chạy tiếp.
Hai request kiểm tra này tốn rất ít ngân sách nhưng tránh được trường hợp chạy cả lô rồi mới phát hiện thiếu quyền. Lab chạy hai bước này trên server giả lập, bước /users/me với api.notion.com thật chỉ thử với token giả.
Thu dữ liệu Notion API bằng Python có phân trang cursor theo đúng nguồn
Phần này đưa vòng lặp cursor cho block children, hàm đệ quy cho cây block và vòng lặp truy vấn data source, tất cả chạy trên server giả lập.
has_more và next_cursor

Cursor và has_more
Trang phân trang của Notion ghi phản hồi danh sách có has_more và next_cursor. Khi has_more là true, gửi next_cursor vào start_cursor để lấy trang sau. Tham số page_size mặc định 100, tối đa 100.
Tài liệu phiên bản nhấn mạnh next_cursor là chuỗi mờ, có thể chứa thông tin phiên, phải gửi lại nguyên văn. Server giả lập dùng cursor dạng cur-5-opaque, code của lab không đọc nội dung cursor mà chỉ chuyển tiếp.
Vòng lặp block children
Hàm children của lab gọi một block, đi theo next_cursor tới khi has_more là false. Gặp 404 thì ghi block ID vào danh sách thiếu quyền và trả về phần đã đọc.
def children(bid, size=5):
out = []; cur = None
while True:
p = {"page_size": size}
if cur: p["start_cursor"] = cur
r = S.get(f"{B}/blocks/{bid}/children", params=p, timeout=10)
if r.status_code == 404: missing.append(bid); return out
d = r.json(); out += d["results"]
if not d["has_more"]: return out
cur = d["next_cursor"]
Page giả lập có 13 block ở tầng đầu. Với page_size 5, cần 3 lần gọi cho tầng đầu.
Đệ quy theo has_children
Hàm tree gọi children cho page, rồi với mỗi block có has_children là true thì gọi tiếp cho block đó, tăng độ sâu thêm một. Lab đặt độ sâu tối đa 5 để tránh vòng lặp không dừng nếu dữ liệu bất thường.
Kết quả: cây có 17 nút, độ sâu lớn nhất là 2, tổng 6 lần gọi API. Các loại block gồm heading_2, paragraph, toggle, code, bulleted_list_item, child_page và unsupported. Toggle "Chi tiet loi 407" ở tầng 0 chứa đoạn văn, khối code và một gạch đầu dòng có con ở tầng 2.
Trang con và block unsupported
Block child_page là page con nằm trong page cha. Lab gọi tiếp nội dung page con và nhận 404 object_not_found, vì trong server giả lập page con này không được chia sẻ. Block ID b040 được ghi vào danh sách thiếu quyền.
Block unsupported là loại API chưa hỗ trợ trả nội dung. Code nên ghi lại loại block này thay vì bỏ qua im lặng, để người đọc file xuất biết có một phần nội dung không lấy được.
Mỗi tầng block là một request riêng, nên số request tăng theo độ sâu và độ rộng của cây.
Truy vấn data source
Vòng lặp truy vấn data source gửi page_size và start_cursor trong thân JSON, không phải tham số URL. Server giả lập có 7 dòng, page_size 3.
rows = []; cur = None
while True:
body = {"page_size": 3}
if cur: body["start_cursor"] = cur
r = S.post(f"{B}/data_sources/{DS_ID}/query", json=body, timeout=10)
if r.status_code == 429: time.sleep(float(r.headers.get("Retry-After", "5"))); continue
d = r.json(); rows += d["results"]
if not d["has_more"]: break
cur = d["next_cursor"]
Kết quả: 7 dòng sau 4 lần gọi, trong đó 1 lần nhận 429 với rate_limit_reason là public_api_request_rate_limit và Retry-After 1, thử lại thành công.
Nhịp gọi cho cây lớn
Page có 500 block chia nhiều tầng có thể cần hàng chục tới hàng trăm request. Với ngân sách 180 request mỗi phút, sao lưu cả workspace cần chia lô và nghỉ giữa các page. Đọc Retry-After và chờ đúng thời gian đó khi gặp 429.
Bài rate limit API khi dùng proxy giải thích vì sao giới hạn tính theo connection không giải được bằng cách đổi IP.
Đối soát ID, kiểu dữ liệu, giá trị thiếu và xuất xứ trong Notion API bằng Python
Thu dữ liệu xong, phần này chuẩn hóa thuộc tính, giữ null và ghi xuất xứ.
Thuộc tính có kiểu riêng
Mỗi thuộc tính của dòng data source có trường type, giá trị nằm trong đối tượng cùng tên với type. Thuộc tính title chứa mảng rich_text, status chứa đối tượng có name, number chứa số, date chứa start và có thể có end.
Lab viết hàm prop đọc theo type: title nối plain_text, status lấy name, date lấy start, number giữ nguyên. Hàm trả None khi giá trị là null. Mỗi kiểu thuộc tính mới cần thêm một nhánh, nên ghi lại kiểu chưa xử lý thay vì đoán.
Null không phải rỗng
Trong 7 dòng giả lập, thuộc tính Trang thai có 2 giá trị null, So luong có 1, Gia han có 3. Dòng Proxy 2 có Gia han null, nghĩa là chưa nhập ngày gia hạn, không phải gia hạn hôm nay.
Báo cáo nhắc gia hạn phải liệt kê riêng các dòng thiếu ngày, vì đó chính là những dòng dễ quên nhất. Điền ngày mặc định cho ô null sẽ che mất vấn đề.
in_trash thay cho archived
Từ phiên bản 2026-03-11, trạng thái thùng rác là in_trash. Mọi block và dòng trong server giả lập có in_trash là false. Code đọc nên lọc bỏ hoặc đánh dấu những mục có in_trash là true.
Code viết cho phiên bản cũ đọc trường archived sẽ nhận None với phiên bản mới, và có thể đưa nhầm nội dung trong thùng rác vào bản sao lưu. Đây là lý do cố định phiên bản và đọc hướng dẫn nâng cấp trước khi đổi.
Chuyển cây block sang Markdown

Cây block theo tầng
Khi đã có danh sách nút với type, depth và text, chuyển sang Markdown khá thẳng. heading_2 thành hai dấu thăng, bulleted_list_item thành gạch đầu dòng thụt lề theo depth, code bọc ba dấu backtick kèm ngôn ngữ, toggle thành một dòng in đậm rồi nội dung con thụt vào.
Lab chưa viết bộ chuyển Markdown đầy đủ, chỉ xuất JSON cây block. Phần chuyển đổi là bước xử lý offline, không cần gọi API thêm, nên có thể làm lại bao nhiêu lần cũng được mà không tốn ngân sách request.
Gộp dòng data source với nội dung page
Mỗi dòng data source là một page, nên nó cũng có thể có nội dung block bên trong. Báo cáo chỉ cần thuộc tính thì dừng ở bước truy vấn data source. Nếu cần cả ghi chú trong từng dòng, phải gọi block children cho từng dòng.
Với 7 dòng giả lập, việc này thêm ít nhất 7 request. Với data source vài nghìn dòng, đây là chỗ tốn ngân sách nhất. Chỉ đọc nội dung những dòng thật sự cần, ví dụ dòng có trạng thái hết hạn.
Kiểm tra cây đầy đủ
So số nút trong cây với tổng số phần tử của mọi lần gọi. Lab đọc 17 nút qua 6 lần gọi, khớp với cấu trúc giả lập. Ghi riêng danh sách block trả 404 và block unsupported để biết phần nào của page chưa vào bản xuất.
Xuất xứ từng file
File export cây block của lab có id, type, depth và text cho từng nút. Phần đầu file nên ghi page ID, Notion-Version đã dùng, thời điểm xuất và danh sách block thiếu quyền. Người đọc file biết ngay bản xuất có đủ hay thiếu.
Không lưu thông tin người dùng nếu không cần. Page và block có trường created_by và last_edited_by chứa ID người dùng. Bản xuất tài liệu thường không cần các trường này. Bài JSON và CSV khi crawl dữ liệu gợi ý cách giữ JSON gốc bên cạnh bảng phẳng.
Lưu kết quả, giới hạn request và khi nào Notion API bằng Python thực sự cần proxy
Phần cuối nói về lưu trữ, tải tăng dần và vai trò thật của proxy.
Tải tăng dần theo last_edited_time
Page và block có last_edited_time. Lần chạy sau chỉ cần đọc lại cây của những page có last_edited_time mới hơn lần trước. Page không đổi thì giữ bản cũ. Cách này giảm số request đáng kể với workspace lớn ít thay đổi.
Lab chưa chạy tải tăng dần vì server giả lập không mô phỏng thời gian chỉnh sửa. Đây là đề xuất dựa trên trường dữ liệu tài liệu mô tả.
Cấu trúc thư mục xuất
Một thư mục theo page ID chứa tree.json là cây block, page.md là bản Markdown và meta.json ghi phiên bản, thời điểm xuất và danh sách thiếu quyền. Data source xuất thành một file CSV có cột ID dòng và các thuộc tính.
Thử qua proxy lab
Lab gọi /v1/users/me với token giả qua proxy HTTP cục bộ có xác thực ở cổng 9702. Kết quả là 401 với mã unauthorized, mất 0,736 giây. Proxy chuyển request đi nguyên vẹn, không thay đổi kết quả xác thực.
px = {"https": "http://user1:p%40ss%232026@127.0.0.1:9702"}
r = requests.get("https://api.notion.com/v1/users/me", headers=H, proxies=px, timeout=30)
Kết quả này cho thấy proxy không thay được token, cũng không thay được việc chia sẻ page với connection.
Khi nào proxy thực sự cần
Proxy cần khi máy chạy script nằm trong mạng chỉ cho ra Internet qua proxy, ví dụ máy chủ nội bộ hay máy ảo trong mạng công ty. Khi đó requests cần biến proxies hoặc biến môi trường HTTPS_PROXY. Bài định dạng proxy có cách viết URL proxy có mật khẩu chứa ký tự đặc biệt.
Proxy không tăng ngân sách 180 hay 600 request mỗi phút, vì giới hạn tính theo connection. Proxy cũng không mở được page chưa chia sẻ.
Chọn loại proxy khi cần
Khi cần một đường ra Internet ổn định cho máy chủ nội bộ, proxy datacenter hoặc proxy dân cư tĩnh là đủ. ProxyVN có proxy dân cư tĩnh, proxy datacenter, proxy 4G và proxy xoay, hỗ trợ HTTP và SOCKS5. Anh em có thể mua proxy giá rẻ tại ProxyVN rồi khai báo vào Session của requests như đoạn mã trên.
Giới hạn suy luận của bài
Phần gọi thật gồm các request không token, token giả và các giá trị Notion-Version khác nhau tới api.notion.com ngày 29/10/2026, Python 3.12.10, requests 2.34.2. Lab không có workspace Notion, không đọc được page thật nào.
Cây block, cursor, data source, 404 thiếu chia sẻ và 429 chạy trên server giả lập dựng theo tài liệu. Mã missing_version và invalid_request_url là mã lab tự đặt. Số liệu giới hạn request lấy từ tài liệu, lab chưa chạm giới hạn thật. Proxy trong lab là proxy cục bộ.
Checklist Notion API bằng Python

Checklist Notion API
- Tạo integration chỉ đọc và chia sẻ đúng page, data source cần dùng.
- Gửi Authorization Bearer và Notion-Version cố định, ví dụ 2026-03-11.
- Phân biệt hai thông báo 401: thiếu header và token không hợp lệ.
- Đi theo next_cursor nguyên văn, page_size tối đa 100.
- Đệ quy theo has_children, đặt độ sâu tối đa.
- Ghi lại block 404 và block unsupported thay vì bỏ qua.
- Giữ null trong thuộc tính, lọc in_trash là true.
- Retry theo Retry-After khi gặp 429 rate_limited.
Câu hỏi thường gặp về Notion API bằng Python
Vì sao API trả 404 dù page có thật?
Thường do page chưa được chia sẻ với integration. Mở page trong Notion, thêm connection vào phần chia sẻ, rồi gọi lại.
Page đã chia sẻ công khai trên web có đọc được bằng API không?
Không, nếu không có token. Lab gọi không có header Authorization và nhận 401. Quyền web và quyền API là hai hệ riêng.
Nên dùng phiên bản API nào?
Lúc lab đọc tài liệu, phiên bản mới nhất là 2026-03-11. Cố định một phiên bản trong code và đọc hướng dẫn nâng cấp trước khi đổi.
Vì sao code cũ truy vấn database bị lỗi?
Từ phiên bản 2025-09-03, dữ liệu bảng nằm trong data source. Đổi sang truy vấn data source theo hướng dẫn nâng cấp của Notion.
Lấy toàn bộ nội dung page trong một request được không?
Không. Mỗi tầng block cần gọi riêng. Page giả lập có 17 nút cần 6 request.
Proxy có giúp tránh lỗi 429 không?
Không. Giới hạn tính theo connection. Hãy đọc Retry-After và giảm nhịp gọi. Bài cài đặt Python proxy từ thư viện requests hướng dẫn khai báo proxy khi mạng thật sự cần.
Notion API bằng Python và những điều cần nhớ
Notion API bằng Python cần ba thứ đi cùng nhau: token hợp lệ, page được chia sẻ với integration và header Notion-Version cố định. Lab ngày 29/10/2026 ghi lại hai thông báo 401 khác nhau từ api.notion.com, rồi đọc cây 17 block qua 6 request, truy vấn 7 dòng data source có retry 429 trên server giả lập theo tài liệu. Giữ null, ghi lại block thiếu quyền và lọc in_trash. Cần đường ra mạng ổn định cho máy chủ khi làm Notion API bằng Python, liên hệ Proxy.vn - Nhà cung cấp dịch vụ proxy chất lượng hàng đầu Việt Nam.