diff --git a/README.md b/README.md
index 900a2451..4c09f984 100644
--- a/README.md
+++ b/README.md
@@ -117,6 +117,7 @@ var complexFiler = new CompoundFilter(
- [x] Users
- [x] Retrieve a User
- [x] List all users
+ - [x] Retrieve your token's bot user
- [x] Search
## Contribution Guideline
diff --git a/Src/Notion.Client/Api/ApiEndpoints.cs b/Src/Notion.Client/Api/ApiEndpoints.cs
index 8e68e22b..7884123c 100644
--- a/Src/Notion.Client/Api/ApiEndpoints.cs
+++ b/Src/Notion.Client/Api/ApiEndpoints.cs
@@ -1,4 +1,6 @@
-namespace Notion.Client
+using System;
+
+namespace Notion.Client
{
public static class ApiEndpoints
{
@@ -15,6 +17,12 @@ public static class UsersApiUrls
{
public static string Retrieve(string userId) => $"/v1/users/{userId}";
public static string List() => "/v1/users";
+
+ ///
+ /// Get the for retrieve your token's bot user.
+ ///
+ /// Returns a retrieve your token's bot user.
+ public static string Me() => "/v1/users/me";
}
public static class BlocksApiUrls
diff --git a/Src/Notion.Client/Api/Users/IUsersClient.cs b/Src/Notion.Client/Api/Users/IUsersClient.cs
index 6eab0cde..95427f2b 100644
--- a/Src/Notion.Client/Api/Users/IUsersClient.cs
+++ b/Src/Notion.Client/Api/Users/IUsersClient.cs
@@ -6,5 +6,11 @@ public interface IUsersClient
{
Task RetrieveAsync(string userId);
Task> ListAsync();
+
+ ///
+ /// Retrieves the bot User associated with the API token provided in the authorization header.
+ ///
+ /// User object of type bot having an owner field with information about the person who authorized the integration.
+ Task MeAsync();
}
}
diff --git a/Src/Notion.Client/Api/Users/UsersClient.cs b/Src/Notion.Client/Api/Users/UsersClient.cs
index 0d2e2c90..5c745f72 100644
--- a/Src/Notion.Client/Api/Users/UsersClient.cs
+++ b/Src/Notion.Client/Api/Users/UsersClient.cs
@@ -21,5 +21,14 @@ public async Task> ListAsync()
{
return await _client.GetAsync>(UsersApiUrls.List());
}
+
+ ///
+ /// Retrieves the bot User associated with the API token provided in the authorization header.
+ ///
+ /// User object of type bot having an owner field with information about the person who authorized the integration.
+ public async Task MeAsync()
+ {
+ return await _client.GetAsync(UsersApiUrls.Me());
+ }
}
}
diff --git a/Src/Notion.Client/Models/User/Bot.cs b/Src/Notion.Client/Models/User/Bot.cs
new file mode 100644
index 00000000..2eaf6420
--- /dev/null
+++ b/Src/Notion.Client/Models/User/Bot.cs
@@ -0,0 +1,10 @@
+using Newtonsoft.Json;
+
+namespace Notion.Client
+{
+ public class Bot
+ {
+ [JsonProperty("owner")]
+ public IBotOwner Owner { get; set; }
+ }
+}
diff --git a/Src/Notion.Client/Models/User/BotOwner/IBotOwner.cs b/Src/Notion.Client/Models/User/BotOwner/IBotOwner.cs
new file mode 100644
index 00000000..61a7a887
--- /dev/null
+++ b/Src/Notion.Client/Models/User/BotOwner/IBotOwner.cs
@@ -0,0 +1,14 @@
+using JsonSubTypes;
+using Newtonsoft.Json;
+
+namespace Notion.Client
+{
+ [JsonConverter(typeof(JsonSubtypes), "type")]
+ [JsonSubtypes.KnownSubType(typeof(UserOwner), "user")]
+ [JsonSubtypes.KnownSubType(typeof(WorkspaceIntegrationOwner), "workspace")]
+ public interface IBotOwner
+ {
+ [JsonProperty("type")]
+ string Type { get; set; }
+ }
+}
diff --git a/Src/Notion.Client/Models/User/BotOwner/UserOwner.cs b/Src/Notion.Client/Models/User/BotOwner/UserOwner.cs
new file mode 100644
index 00000000..40d69867
--- /dev/null
+++ b/Src/Notion.Client/Models/User/BotOwner/UserOwner.cs
@@ -0,0 +1,12 @@
+using Newtonsoft.Json;
+
+namespace Notion.Client
+{
+ public class UserOwner : IBotOwner
+ {
+ public string Type { get; set; }
+
+ [JsonProperty("user")]
+ public User User { get; set; }
+ }
+}
diff --git a/Src/Notion.Client/Models/User/BotOwner/WorkspaceIntegrationOwner.cs b/Src/Notion.Client/Models/User/BotOwner/WorkspaceIntegrationOwner.cs
new file mode 100644
index 00000000..78a84f6f
--- /dev/null
+++ b/Src/Notion.Client/Models/User/BotOwner/WorkspaceIntegrationOwner.cs
@@ -0,0 +1,12 @@
+using Newtonsoft.Json;
+
+namespace Notion.Client
+{
+ public class WorkspaceIntegrationOwner : IBotOwner
+ {
+ public string Type { get; set; }
+
+ [JsonProperty("workspace")]
+ public bool Workspace { get; set; }
+ }
+}
diff --git a/Src/Notion.Client/Models/User/Person.cs b/Src/Notion.Client/Models/User/Person.cs
new file mode 100644
index 00000000..621f3b48
--- /dev/null
+++ b/Src/Notion.Client/Models/User/Person.cs
@@ -0,0 +1,10 @@
+using Newtonsoft.Json;
+
+namespace Notion.Client
+{
+ public class Person
+ {
+ [JsonProperty("email")]
+ public string Email { get; set; }
+ }
+}
diff --git a/Src/Notion.Client/Models/User.cs b/Src/Notion.Client/Models/User/User.cs
similarity index 79%
rename from Src/Notion.Client/Models/User.cs
rename to Src/Notion.Client/Models/User/User.cs
index ce39e822..7f336929 100644
--- a/Src/Notion.Client/Models/User.cs
+++ b/Src/Notion.Client/Models/User/User.cs
@@ -22,15 +22,4 @@ public class User : IObject
[JsonProperty("bot")]
public Bot Bot { get; set; }
}
-
- public class Person
- {
- [JsonProperty("email")]
- public string Email { get; set; }
- }
-
- public class Bot
- {
-
- }
}
diff --git a/Test/Notion.UnitTests/Notion.UnitTests.csproj b/Test/Notion.UnitTests/Notion.UnitTests.csproj
index 8382e6bc..3b729bf5 100644
--- a/Test/Notion.UnitTests/Notion.UnitTests.csproj
+++ b/Test/Notion.UnitTests/Notion.UnitTests.csproj
@@ -81,6 +81,12 @@
Always
+
+ Always
+
+
+ Always
+
Always
diff --git a/Test/Notion.UnitTests/UserClientTest.cs b/Test/Notion.UnitTests/UserClientTest.cs
index a6ea75ef..d9b27984 100644
--- a/Test/Notion.UnitTests/UserClientTest.cs
+++ b/Test/Notion.UnitTests/UserClientTest.cs
@@ -78,5 +78,72 @@ public async Task RetrieveUser()
user.Person.Email.Should().Be("vedkoditkar@gmail.com");
user.Bot.Should().BeNull();
}
+
+ [Fact]
+ public async Task RetrieveTokenUser_WorkspaceInternalToken()
+ {
+ // Arrange
+ var jsonData = await File.ReadAllTextAsync("data/users/MeResponse.json");
+
+ var path = ApiEndpoints.UsersApiUrls.Me();
+
+ Server.Given(CreateGetRequestBuilder(path))
+ .RespondWith(
+ Response.Create()
+ .WithStatusCode(200)
+ .WithBody(jsonData)
+ );
+
+ // Act
+ var user = await _client.MeAsync();
+
+ // Assert
+ user.Id.Should().Be("590693f3-797f-4970-98ff-7284106393e5");
+ user.Name.Should().Be("Test");
+ user.AvatarUrl.Should().BeNull();
+ user.Type.Should().Be("bot");
+ user.Person.Should().BeNull();
+ user.Bot.Should().NotBeNull();
+ user.Bot.Owner.Should().BeOfType();
+
+ var owner = (WorkspaceIntegrationOwner)user.Bot.Owner;
+ owner.Workspace.Should().BeTrue();
+ }
+
+ [Fact]
+ public async Task RetrieveTokenUser_UserLevelToken()
+ {
+ // Arrange
+ var jsonData = await File.ReadAllTextAsync("data/users/MeUserLevelResponse.json");
+
+ var path = ApiEndpoints.UsersApiUrls.Me();
+
+ Server.Given(CreateGetRequestBuilder(path))
+ .RespondWith(
+ Response.Create()
+ .WithStatusCode(200)
+ .WithBody(jsonData)
+ );
+
+ // Act
+ var user = await _client.MeAsync();
+
+ // Assert
+ user.Id.Should().Be("16d84278-ab0e-484c-9bdd-b35da3bd8905");
+ user.Name.Should().Be("pied piper");
+ user.AvatarUrl.Should().BeNull();
+ user.Type.Should().Be("bot");
+ user.Person.Should().BeNull();
+ user.Bot.Should().NotBeNull();
+ user.Bot.Owner.Should().BeOfType();
+
+ var owner = (UserOwner)user.Bot.Owner;
+ owner.User.Id.Should().Be("5389a034-eb5c-47b5-8a9e-f79c99ef166c");
+ owner.User.Name.Should().Be("christine makenotion");
+ owner.User.AvatarUrl.Should().BeNull();
+ owner.User.Type.Should().Be("person");
+ owner.User.Person.Email.Should().Be("christine@makenotion.com");
+ owner.User.Bot.Should().BeNull();
+ }
}
}
diff --git a/Test/Notion.UnitTests/data/users/MeResponse.json b/Test/Notion.UnitTests/data/users/MeResponse.json
new file mode 100644
index 00000000..411af097
--- /dev/null
+++ b/Test/Notion.UnitTests/data/users/MeResponse.json
@@ -0,0 +1,13 @@
+{
+ "object": "user",
+ "id": "590693f3-797f-4970-98ff-7284106393e5",
+ "name": "Test",
+ "avatar_url": null,
+ "type": "bot",
+ "bot": {
+ "owner": {
+ "type": "workspace",
+ "workspace": true
+ }
+ }
+}
diff --git a/Test/Notion.UnitTests/data/users/MeUserLevelResponse.json b/Test/Notion.UnitTests/data/users/MeUserLevelResponse.json
new file mode 100644
index 00000000..cbeec973
--- /dev/null
+++ b/Test/Notion.UnitTests/data/users/MeUserLevelResponse.json
@@ -0,0 +1,22 @@
+{
+ "object": "user",
+ "id": "16d84278-ab0e-484c-9bdd-b35da3bd8905",
+ "name": "pied piper",
+ "avatar_url": null,
+ "type": "bot",
+ "bot": {
+ "owner": {
+ "type": "user",
+ "user": {
+ "object": "user",
+ "id": "5389a034-eb5c-47b5-8a9e-f79c99ef166c",
+ "name": "christine makenotion",
+ "avatar_url": null,
+ "type": "person",
+ "person": {
+ "email": "christine@makenotion.com"
+ }
+ }
+ }
+ }
+}
diff --git a/docs/README.md b/docs/README.md
index 4088b54b..542fe472 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -84,6 +84,7 @@ var complexFiler = new CompoundFilter(
- [x] Users
- [x] Retrieve a User
- [x] List all users
+ - [x] Retrieve your token's bot user
- [x] Search
## Contribution Guideline