diff --git a/Gemfile b/Gemfile
index 79a6eb5a89c2538496ac25d0f6ccb9cfdffa8899..3472389b0ce73d38c61c5415934cefb34cabfc67 100644
--- a/Gemfile
+++ b/Gemfile
@@ -12,7 +12,7 @@ gem "unicorn", "5.0.1", require: false
 
 # Federation
 
-gem "diaspora_federation-rails", "0.0.12"
+gem "diaspora_federation-rails", "0.0.13"
 
 # API and JSON
 
@@ -168,7 +168,7 @@ gem "addressable",        "2.3.8", require: "addressable/uri"
 gem "faraday",            "0.9.2"
 gem "faraday_middleware", "0.10.0"
 gem "faraday-cookie_jar", "0.0.6"
-gem "typhoeus",           "0.8.0"
+gem "typhoeus",           "1.0.1"
 
 # Views
 
@@ -291,7 +291,7 @@ group :test do
   gem "webmock",            "1.22.6", require: false
   gem "shoulda-matchers",   "3.1.1"
 
-  gem "diaspora_federation-test", "0.0.12"
+  gem "diaspora_federation-test", "0.0.13"
 end
 
 group :development, :test do
diff --git a/Gemfile.lock b/Gemfile.lock
index 6baa27335343db83ec4b8923d5cfad3b59b85bf8..f30b592d6aba9ed088e42d7f37862356c60a7763 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -180,17 +180,17 @@ GEM
       eventmachine (~> 1.0.8)
       http_parser.rb (~> 0.6)
       nokogiri (~> 1.6)
-    diaspora_federation (0.0.12)
+    diaspora_federation (0.0.13)
       faraday (~> 0.9.0)
       faraday_middleware (~> 0.10.0)
-      nokogiri (~> 1.6, >= 1.6.7.1)
-      typhoeus (~> 0.7)
+      nokogiri (~> 1.6, >= 1.6.7.2)
+      typhoeus (~> 1.0)
       valid (~> 1.0)
-    diaspora_federation-rails (0.0.12)
-      diaspora_federation (= 0.0.12)
+    diaspora_federation-rails (0.0.13)
+      diaspora_federation (= 0.0.13)
       rails (~> 4.2)
-    diaspora_federation-test (0.0.12)
-      diaspora_federation (= 0.0.12)
+    diaspora_federation-test (0.0.13)
+      diaspora_federation (= 0.0.13)
       factory_girl (~> 4.5, >= 4.5.0)
     diff-lcs (1.2.5)
     docile (1.1.5)
@@ -846,7 +846,7 @@ GEM
       simple_oauth (~> 0.3.0)
     twitter-text (1.13.3)
       unf (~> 0.1.0)
-    typhoeus (0.8.0)
+    typhoeus (1.0.1)
       ethon (>= 0.8.0)
     tzinfo (1.2.2)
       thread_safe (~> 0.1)
@@ -916,8 +916,8 @@ DEPENDENCIES
   devise-token_authenticatable (~> 0.4.0)
   devise_lastseenable (= 0.0.6)
   diaspora-vines (~> 0.2.0.develop)
-  diaspora_federation-rails (= 0.0.12)
-  diaspora_federation-test (= 0.0.12)
+  diaspora_federation-rails (= 0.0.13)
+  diaspora_federation-test (= 0.0.13)
   entypo-rails (= 3.0.0.pre.rc2)
   eye (= 0.8)
   factory_girl_rails (= 4.6.0)
@@ -1029,7 +1029,7 @@ DEPENDENCIES
   turbo_dev_assets (= 0.0.2)
   twitter (= 5.16.0)
   twitter-text (= 1.13.3)
-  typhoeus (= 0.8.0)
+  typhoeus (= 1.0.1)
   uglifier (= 2.7.2)
   unicorn (= 5.0.1)
   uuid (= 2.3.8)
diff --git a/config/initializers/diaspora_federation.rb b/config/initializers/diaspora_federation.rb
index 1fa4b18e6772dbb55c4376f40f8225e7f524004a..a1cda14d9f61b7ec3f580b5ef732f4f52c1b1068 100644
--- a/config/initializers/diaspora_federation.rb
+++ b/config/initializers/diaspora_federation.rb
@@ -106,7 +106,20 @@ DiasporaFederation.configure do |config|
       end
     end
 
-    on :save_entity_after_receive do
+    on :receive_entity do
+      # TODO
+    end
+
+    on :fetch_public_entity do |entity_type, guid|
+      entity = entity_type.constantize.find_by(guid: guid, public: true)
+      Diaspora::Federation.post(entity) if entity.is_a? Post
+    end
+
+    on :fetch_person_url_to do |diaspora_id, path|
+      Person.find_by(diaspora_handle: diaspora_id).send(:url_to, path)
+    end
+
+    on :update_pod do
       # TODO
     end
   end
diff --git a/lib/diaspora.rb b/lib/diaspora.rb
index 6f6d2002cd6177ebc66638646a70730224ad102d..2cf2579c2b9cb54f8474a3eda5f674866fa2307e 100644
--- a/lib/diaspora.rb
+++ b/lib/diaspora.rb
@@ -3,13 +3,14 @@
 #   the COPYRIGHT file.
 
 module Diaspora
-  require 'diaspora/camo'
-  require 'diaspora/exceptions'
-  require 'diaspora/exporter'
-  require 'diaspora/federated'
-  require 'diaspora/fetcher'
-  require 'diaspora/markdownify'
-  require 'diaspora/mentionable'
-  require 'diaspora/message_renderer'
-  require 'diaspora/parser'
+  require "diaspora/camo"
+  require "diaspora/exceptions"
+  require "diaspora/exporter"
+  require "diaspora/federated"
+  require "diaspora/federation"
+  require "diaspora/fetcher"
+  require "diaspora/markdownify"
+  require "diaspora/mentionable"
+  require "diaspora/message_renderer"
+  require "diaspora/parser"
 end
diff --git a/lib/diaspora/federation.rb b/lib/diaspora/federation.rb
new file mode 100644
index 0000000000000000000000000000000000000000..710e3349e49947ba4c187b2e9ef4372a50be3d4c
--- /dev/null
+++ b/lib/diaspora/federation.rb
@@ -0,0 +1,78 @@
+module Diaspora
+  module Federation
+    def self.post(post)
+      case post
+      when StatusMessage
+        status_message(post)
+      when Reshare
+        reshare(post)
+      else
+        raise ArgumentError, "unknown post-class: #{post.class}"
+      end
+    end
+
+    def self.location(location)
+      DiasporaFederation::Entities::Location.new(
+        address: location.address,
+        lat:     location.lat,
+        lng:     location.lng
+      )
+    end
+
+    def self.photo(photo)
+      DiasporaFederation::Entities::Photo.new(
+        author:              photo.diaspora_handle,
+        guid:                photo.guid,
+        public:              photo.public,
+        created_at:          photo.created_at,
+        remote_photo_path:   photo.remote_photo_path,
+        remote_photo_name:   photo.remote_photo_name,
+        text:                photo.text,
+        status_message_guid: photo.status_message_guid,
+        height:              photo.height,
+        width:               photo.width
+      )
+    end
+
+    def self.poll(poll)
+      DiasporaFederation::Entities::Poll.new(
+        guid:         poll.guid,
+        question:     poll.question,
+        poll_answers: poll.poll_answers.map {|answer| poll_answer(answer) }
+      )
+    end
+
+    def self.poll_answer(poll_answer)
+      DiasporaFederation::Entities::PollAnswer.new(
+        guid:   poll_answer.guid,
+        answer: poll_answer.answer
+      )
+    end
+
+    def self.reshare(reshare)
+      DiasporaFederation::Entities::Reshare.new(
+        root_author:           reshare.root_diaspora_id,
+        root_guid:             reshare.root_guid,
+        author:                reshare.diaspora_handle,
+        guid:                  reshare.guid,
+        public:                reshare.public,
+        created_at:            reshare.created_at,
+        provider_display_name: reshare.provider_display_name
+      )
+    end
+
+    def self.status_message(status_message)
+      DiasporaFederation::Entities::StatusMessage.new(
+        author:                status_message.diaspora_handle,
+        guid:                  status_message.guid,
+        raw_message:           status_message.raw_message,
+        photos:                status_message.photos.map {|photo| photo(photo) },
+        location:              status_message.location ? location(status_message.location) : nil,
+        poll:                  status_message.poll ? poll(status_message.poll) : nil,
+        public:                status_message.public,
+        created_at:            status_message.created_at,
+        provider_display_name: status_message.provider_display_name
+      )
+    end
+  end
+end
diff --git a/spec/federation_callbacks_spec.rb b/spec/federation_callbacks_spec.rb
index a775d5ecc5e86e9eb1a40d72962d6d984d4fb8a1..0de40cf4965443ddb7c4ef142833ee59776d53d5 100644
--- a/spec/federation_callbacks_spec.rb
+++ b/spec/federation_callbacks_spec.rb
@@ -296,4 +296,58 @@ describe "diaspora federation callbacks" do
       expect(result).to be_falsey
     end
   end
+
+  describe ":fetch_public_entity" do
+    it "fetches a Post" do
+      post = FactoryGirl.create(:status_message, author: alice.person, public: true)
+      entity = DiasporaFederation.callbacks.trigger(:fetch_public_entity, "Post", post.guid)
+
+      expect(entity.guid).to eq(post.guid)
+      expect(entity.author).to eq(alice.diaspora_handle)
+      expect(entity.public).to be_truthy
+    end
+
+    it "fetches a StatusMessage" do
+      post = FactoryGirl.create(:status_message, author: alice.person, public: true)
+      entity = DiasporaFederation.callbacks.trigger(:fetch_public_entity, "StatusMessage", post.guid)
+
+      expect(entity.guid).to eq(post.guid)
+      expect(entity.author).to eq(alice.diaspora_handle)
+      expect(entity.public).to be_truthy
+    end
+
+    it "fetches a Reshare" do
+      post = FactoryGirl.create(:reshare, author: alice.person, public: true)
+      entity = DiasporaFederation.callbacks.trigger(:fetch_public_entity, "Reshare", post.guid)
+
+      expect(entity.guid).to eq(post.guid)
+      expect(entity.author).to eq(alice.diaspora_handle)
+      expect(entity.public).to be_truthy
+    end
+
+    it "does not fetch a private post" do
+      post = FactoryGirl.create(:status_message, author: alice.person, public: false)
+
+      expect(
+        DiasporaFederation.callbacks.trigger(:fetch_public_entity, "StatusMessage", post.guid)
+      ).to be_nil
+    end
+
+    it "returns nil, if the post is unknown" do
+      expect(
+        DiasporaFederation.callbacks.trigger(:fetch_public_entity, "Post", "unknown-guid")
+      ).to be_nil
+    end
+  end
+
+  describe ":fetch_person_url_to" do
+    it "returns the url with with the pod of the person" do
+      pod = FactoryGirl.create(:pod)
+      person = FactoryGirl.create(:person, pod: pod)
+
+      expect(
+        DiasporaFederation.callbacks.trigger(:fetch_person_url_to, person.diaspora_handle, "/path/on/pod")
+      ).to eq("https://#{pod.host}/path/on/pod")
+    end
+  end
 end
diff --git a/spec/integration/federation/federation_helper.rb b/spec/integration/federation/federation_helper.rb
index 4321e4f29b2bce2010048c2e8d4d5b3bdf9c8f61..e33a437350585f26d0fc15ca66cc079281fbf98c 100644
--- a/spec/integration/federation/federation_helper.rb
+++ b/spec/integration/federation/federation_helper.rb
@@ -23,11 +23,10 @@ def create_remote_user(pod)
 end
 
 def create_relayable_entity(entity_name, target, diaspora_id, parent_author_key)
-  target_entity_type = FactoryGirl.factory_by_name(entity_name).build_class.get_target_entity_type(@entity.to_h)
   expect(DiasporaFederation.callbacks).to receive(:trigger)
                                             .with(
                                               :fetch_author_private_key_by_entity_guid,
-                                              target_entity_type,
+                                              FactoryGirl.build(entity_name).parent_type,
                                               target.guid
                                             )
                                             .and_return(parent_author_key)
@@ -36,19 +35,18 @@ def create_relayable_entity(entity_name, target, diaspora_id, parent_author_key)
     entity_name,
     conversation_guid: target.guid,
     parent_guid:       target.guid,
-    diaspora_id:       diaspora_id,
+    author:            diaspora_id,
     poll_answer_guid:  target.respond_to?(:poll_answers) ? target.poll_answers.first.guid : nil
   )
 end
 
 def generate_xml(entity, remote_user, recipient=nil)
   if recipient
-    DiasporaFederation::Salmon::EncryptedSlap.generate_xml(
+    DiasporaFederation::Salmon::EncryptedSlap.prepare(
       remote_user.diaspora_handle,
       OpenSSL::PKey::RSA.new(remote_user.encryption_key),
-      entity,
-      OpenSSL::PKey::RSA.new(recipient.encryption_key)
-    )
+      entity
+    ).generate_xml(OpenSSL::PKey::RSA.new(recipient.encryption_key))
   else
     DiasporaFederation::Salmon::Slap.generate_xml(
       remote_user.diaspora_handle,
diff --git a/spec/integration/federation/receive_federation_messages_spec.rb b/spec/integration/federation/receive_federation_messages_spec.rb
index 24ab2a1a2f8d53e58559dd5202196770854e092c..537bad5cf3d0a018dfacf7546cb5cf042d27c759 100644
--- a/spec/integration/federation/receive_federation_messages_spec.rb
+++ b/spec/integration/federation/receive_federation_messages_spec.rb
@@ -36,7 +36,7 @@ describe "Receive federation messages feature" do
       it "reshare of public post passes" do
         post = FactoryGirl.create(:status_message, author: alice.person, public: true)
         reshare = FactoryGirl.build(
-          :reshare_entity, root_diaspora_id: alice.diaspora_handle, root_guid: post.guid, diaspora_id: sender_id)
+          :reshare_entity, root_author: alice.diaspora_handle, root_guid: post.guid, author: sender_id)
         post_message(generate_xml(reshare, sender))
 
         expect(Reshare.exists?(root_guid: post.guid)).to be_truthy
@@ -46,7 +46,7 @@ describe "Receive federation messages feature" do
       it "reshare of private post fails" do
         post = FactoryGirl.create(:status_message, author: alice.person, public: false)
         reshare = FactoryGirl.build(
-          :reshare_entity, root_diaspora_id: alice.diaspora_handle, root_guid: post.guid, diaspora_id: sender_id)
+          :reshare_entity, root_author: alice.diaspora_handle, root_guid: post.guid, author: sender_id)
         expect {
           post_message(generate_xml(reshare, sender))
         }.to raise_error ActiveRecord::RecordInvalid, "Validation failed: Only posts which are public may be reshared."
@@ -73,7 +73,7 @@ describe "Receive federation messages feature" do
     let(:recipient) { alice }
 
     it "treats sharing request recive correctly" do
-      entity = FactoryGirl.build(:request_entity, recipient_id: alice.diaspora_handle)
+      entity = FactoryGirl.build(:request_entity, recipient: alice.diaspora_handle)
 
       expect(Diaspora::Fetcher::Public).to receive(:queue_for).exactly(1).times
 
@@ -95,7 +95,7 @@ describe "Receive federation messages feature" do
     end
 
     it "doesn't save the private status message if there is no sharing" do
-      entity = FactoryGirl.build(:status_message_entity, diaspora_id: sender_id, public: false)
+      entity = FactoryGirl.build(:status_message_entity, author: sender_id, public: false)
       post_message(generate_xml(entity, sender, alice), alice)
 
       expect(StatusMessage.exists?(guid: entity.guid)).to be_falsey
@@ -112,7 +112,7 @@ describe "Receive federation messages feature" do
       it_behaves_like "messages which can't be send without sharing"
 
       it "treats profile receive correctly" do
-        entity = FactoryGirl.build(:profile_entity, diaspora_id: sender_id)
+        entity = FactoryGirl.build(:profile_entity, author: sender_id)
         post_message(generate_xml(entity, sender, alice), alice)
 
         expect(Profile.exists?(diaspora_handle: entity.diaspora_id)).to be_truthy
@@ -121,8 +121,8 @@ describe "Receive federation messages feature" do
       it "receives conversation correctly" do
         entity = FactoryGirl.build(
           :conversation_entity,
-          diaspora_id:     sender_id,
-          participant_ids: "#{sender_id};#{alice.diaspora_handle}"
+          author:       sender_id,
+          participants: "#{sender_id};#{alice.diaspora_handle}"
         )
         post_message(generate_xml(entity, sender, alice), alice)
 
diff --git a/spec/integration/federation/shared_receive_retraction.rb b/spec/integration/federation/shared_receive_retraction.rb
index c9182e53977f02ca110bf81008d00330be159588..e4e2612a7e9aad055a448e6354b6107fc438a34a 100644
--- a/spec/integration/federation/shared_receive_retraction.rb
+++ b/spec/integration/federation/shared_receive_retraction.rb
@@ -9,7 +9,7 @@ def retraction_entity(entity_name, target_object, sender)
 
   FactoryGirl.build(
     entity_name,
-    diaspora_id: sender.diaspora_handle,
+    author:      sender.diaspora_handle,
     target_guid: target_object.guid,
     target_type: target_object.class.to_s
   )
diff --git a/spec/integration/federation/shared_receive_stream_items.rb b/spec/integration/federation/shared_receive_stream_items.rb
index 93e876481ce5793427048c087f03c17766696336..6d745683644283349730b3daceb6069772d3c977 100644
--- a/spec/integration/federation/shared_receive_stream_items.rb
+++ b/spec/integration/federation/shared_receive_stream_items.rb
@@ -4,7 +4,7 @@ shared_examples_for "messages which are indifferent about sharing fact" do
   let(:public) { recipient.nil? }
 
   it "treats status message receive correctly" do
-    entity = FactoryGirl.build(:status_message_entity, diaspora_id: sender_id, public: public)
+    entity = FactoryGirl.build(:status_message_entity, author: sender_id, public: public)
 
     post_message(generate_xml(entity, sender, recipient), recipient)
 
@@ -13,7 +13,7 @@ shared_examples_for "messages which are indifferent about sharing fact" do
 
   it "doesn't accept status message with wrong signature" do
     allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024))
-    entity = FactoryGirl.build(:status_message_entity, diaspora_id: sender_id, public: public)
+    entity = FactoryGirl.build(:status_message_entity, author: sender_id, public: public)
 
     post_message(generate_xml(entity, sender, recipient), recipient)