diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index 73ca07e84..7eed0a600 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -54,6 +54,36 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
     end
   end
 
+  def object_likes(conn, %{"uuid" => uuid, "page" => page}) do
+    with ap_id <- o_status_url(conn, :object, uuid),
+         %Object{} = object <- Object.get_cached_by_ap_id(ap_id),
+         {_, true} <- {:public?, ActivityPub.is_public?(object)},
+         likes <- Utils.get_object_likes(object) do
+      {page, _} = Integer.parse(page)
+
+      conn
+      |> put_resp_header("content-type", "application/activity+json")
+      |> json(ObjectView.render("likes.json", ap_id, likes, page))
+    else
+      {:public?, false} ->
+        {:error, :not_found}
+    end
+  end
+
+  def object_likes(conn, %{"uuid" => uuid}) do
+    with ap_id <- o_status_url(conn, :object, uuid),
+         %Object{} = object <- Object.get_cached_by_ap_id(ap_id),
+         {_, true} <- {:public?, ActivityPub.is_public?(object)},
+         likes <- Utils.get_object_likes(object) do
+      conn
+      |> put_resp_header("content-type", "application/activity+json")
+      |> json(ObjectView.render("likes.json", ap_id, likes))
+    else
+      {:public?, false} ->
+        {:error, :not_found}
+    end
+  end
+
   def activity(conn, %{"uuid" => uuid}) do
     with ap_id <- o_status_url(conn, :activity, uuid),
          %Activity{} = activity <- Activity.normalize(ap_id),
@@ -204,6 +234,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
     end
   end
 
+  def handle_user_activity(user, %{"type" => "Like"} = params) do
+    with %Object{} = object <- Object.normalize(params["object"]),
+         {:ok, activity, _object} <- ActivityPub.like(user, object) do
+      {:ok, activity}
+    else
+      _ -> {:error, "Can't like object"}
+    end
+  end
+
   def handle_user_activity(_, _) do
     {:error, "Unhandled activity type"}
   end
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 87b7fc07f..86d11c874 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -629,6 +629,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
     |> add_mention_tags
     |> add_emoji_tags
     |> add_attributed_to
+    |> add_likes
     |> prepare_attachments
     |> set_conversation
     |> set_reply_to_uri
@@ -641,7 +642,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
   #  internal -> Mastodon
   #  """
 
-  def prepare_outgoing(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do
+  def prepare_outgoing(%{"type" => "Create", "object" => object} = data) do
     object =
       object
       |> prepare_object
@@ -788,6 +789,22 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
     |> Map.put("attributedTo", attributedTo)
   end
 
+  def add_likes(%{"id" => id, "like_count" => likes} = object) do
+    likes = %{
+      "id" => "#{id}/likes",
+      "first" => "#{id}/likes?page=1",
+      "type" => "OrderedCollection",
+      "totalItems" => likes
+    }
+
+    object
+    |> Map.put("likes", likes)
+  end
+
+  def add_likes(object) do
+    object
+  end
+
   def prepare_attachments(object) do
     attachments =
       (object["attachment"] || [])
@@ -803,7 +820,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
   defp strip_internal_fields(object) do
     object
     |> Map.drop([
-      "likes",
       "like_count",
       "announcements",
       "announcement_count",
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index b313996db..6ecab773c 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -231,6 +231,27 @@ defmodule Pleroma.Web.ActivityPub.Utils do
     Repo.one(query)
   end
 
+  @doc """
+  Returns like activities targeting an object
+  """
+  def get_object_likes(%{data: %{"id" => id}}) do
+    query =
+      from(
+        activity in Activity,
+        # this is to use the index
+        where:
+          fragment(
+            "coalesce((?)->'object'->>'id', (?)->>'object') = ?",
+            activity.data,
+            activity.data,
+            ^id
+          ),
+        where: fragment("(?)->>'type' = 'Like'", activity.data)
+      )
+
+    Repo.all(query)
+  end
+
   def make_like_data(%User{ap_id: ap_id} = actor, %{data: %{"id" => id}} = object, activity_id) do
     data = %{
       "type" => "Like",
diff --git a/lib/pleroma/web/activity_pub/views/object_view.ex b/lib/pleroma/web/activity_pub/views/object_view.ex
index b5c9bf8d0..193042056 100644
--- a/lib/pleroma/web/activity_pub/views/object_view.ex
+++ b/lib/pleroma/web/activity_pub/views/object_view.ex
@@ -35,4 +35,38 @@ defmodule Pleroma.Web.ActivityPub.ObjectView do
 
     Map.merge(base, additional)
   end
+
+  def render("likes.json", ap_id, likes, page) do
+    collection(likes, "#{ap_id}/likes", page)
+    |> Map.merge(Pleroma.Web.ActivityPub.Utils.make_json_ld_header())
+  end
+
+  def render("likes.json", ap_id, likes) do
+    %{
+      "id" => "#{ap_id}/likes",
+      "type" => "OrderedCollection",
+      "totalItems" => length(likes),
+      "first" => collection(likes, "#{ap_id}/followers", 1)
+    }
+    |> Map.merge(Pleroma.Web.ActivityPub.Utils.make_json_ld_header())
+  end
+
+  def collection(collection, iri, page) do
+    offset = (page - 1) * 10
+    items = Enum.slice(collection, offset, 10)
+    items = Enum.map(items, fn object -> Transmogrifier.prepare_object(object.data) end)
+    total = length(collection)
+
+    map = %{
+      "id" => "#{iri}?page=#{page}",
+      "type" => "OrderedCollectionPage",
+      "partOf" => iri,
+      "totalItems" => total,
+      "orderedItems" => items
+    }
+
+    if offset < total do
+      Map.put(map, "next", "#{iri}?page=#{page + 1}")
+    end
+  end
 end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index a5f4d8126..7a0c9fd25 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -421,6 +421,7 @@ defmodule Pleroma.Web.Router do
     get("/users/:nickname/followers", ActivityPubController, :followers)
     get("/users/:nickname/following", ActivityPubController, :following)
     get("/users/:nickname/outbox", ActivityPubController, :outbox)
+    get("/objects/:uuid/likes", ActivityPubController, :object_likes)
   end
 
   pipeline :activitypub_client do
diff --git a/test/support/factory.ex b/test/support/factory.ex
index 57fa4a79d..4ac77981a 100644
--- a/test/support/factory.ex
+++ b/test/support/factory.ex
@@ -57,6 +57,11 @@ defmodule Pleroma.Factory do
     %Pleroma.Object{data: Map.merge(data, %{"to" => [user2.ap_id]})}
   end
 
+  def article_factory do
+    note_factory()
+    |> Map.put("type", "Article")
+  end
+
   def tombstone_factory do
     data = %{
       "type" => "Tombstone",
@@ -110,6 +115,26 @@ defmodule Pleroma.Factory do
     }
   end
 
+  def article_activity_factory do
+    article = insert(:article)
+
+    data = %{
+      "id" => Pleroma.Web.ActivityPub.Utils.generate_activity_id(),
+      "type" => "Create",
+      "actor" => article.data["actor"],
+      "to" => article.data["to"],
+      "object" => article.data,
+      "published" => DateTime.utc_now() |> DateTime.to_iso8601(),
+      "context" => article.data["context"]
+    }
+
+    %Pleroma.Activity{
+      data: data,
+      actor: data["actor"],
+      recipients: data["to"]
+    }
+  end
+
   def announce_activity_factory do
     note_activity = insert(:note_activity)
     user = insert(:user)
diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs
index 7aed8c71d..52e67f046 100644
--- a/test/web/activity_pub/activity_pub_controller_test.exs
+++ b/test/web/activity_pub/activity_pub_controller_test.exs
@@ -89,6 +89,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
     end
   end
 
+  describe "/object/:uuid/likes" do
+    test "it returns the like activities in a collection", %{conn: conn} do
+      like = insert(:like_activity)
+      uuid = String.split(like.data["object"], "/") |> List.last()
+
+      result =
+        conn
+        |> put_req_header("accept", "application/activity+json")
+        |> get("/objects/#{uuid}/likes")
+        |> json_response(200)
+
+      assert List.first(result["first"]["orderedItems"])["id"] == like.data["id"]
+    end
+  end
+
   describe "/activities/:uuid" do
     test "it returns a json representation of the activity", %{conn: conn} do
       activity = insert(:note_activity)
@@ -292,6 +307,31 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
 
       assert json_response(conn, 400)
     end
+
+    test "it increases like count when receiving a like action", %{conn: conn} do
+      note_activity = insert(:note_activity)
+      user = User.get_cached_by_ap_id(note_activity.data["actor"])
+
+      data = %{
+        type: "Like",
+        object: %{
+          id: note_activity.data["object"]["id"]
+        }
+      }
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> put_req_header("content-type", "application/activity+json")
+        |> post("/users/#{user.nickname}/outbox", data)
+
+      result = json_response(conn, 201)
+      assert Activity.get_by_ap_id(result["id"])
+
+      object = Object.get_by_ap_id(note_activity.data["object"]["id"])
+      assert object
+      assert object.data["like_count"] == 1
+    end
   end
 
   describe "/users/:nickname/followers" do
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index a5fd87ed4..87d0ab559 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -829,12 +829,33 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       assert length(modified["object"]["tag"]) == 2
 
       assert is_nil(modified["object"]["emoji"])
-      assert is_nil(modified["object"]["likes"])
       assert is_nil(modified["object"]["like_count"])
       assert is_nil(modified["object"]["announcements"])
       assert is_nil(modified["object"]["announcement_count"])
       assert is_nil(modified["object"]["context_id"])
     end
+
+    test "it strips internal fields of article" do
+      activity = insert(:article_activity)
+
+      {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
+
+      assert length(modified["object"]["tag"]) == 2
+
+      assert is_nil(modified["object"]["emoji"])
+      assert is_nil(modified["object"]["like_count"])
+      assert is_nil(modified["object"]["announcements"])
+      assert is_nil(modified["object"]["announcement_count"])
+      assert is_nil(modified["object"]["context_id"])
+    end
+
+    test "it adds like collection to object" do
+      activity = insert(:note_activity)
+      {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
+
+      assert modified["object"]["likes"]["type"] == "OrderedCollection"
+      assert modified["object"]["likes"]["totalItems"] == 0
+    end
   end
 
   describe "user upgrade" do