address comments
diff --git a/include/grpc++/generic/generic_stub.h b/include/grpc++/generic/generic_stub.h
index 3c11e55..fdd2377 100644
--- a/include/grpc++/generic/generic_stub.h
+++ b/include/grpc++/generic/generic_stub.h
@@ -50,7 +50,11 @@
   explicit GenericStub(std::shared_ptr<ChannelInterface> channel)
       : channel_(channel) {}
 
-  /// begin a call to a named method
+  /// Begin a call to a named method \a method usign \a context.
+  /// A tag \a tag will be deliever to \a cq when the call has been started
+  /// (i.e, initial metadata has been sent).
+  /// The return value only indicates whether or not registration of the call
+  /// succeeded (i.e. the call won't proceed if the return value is 0).
   std::unique_ptr<GenericClientAsyncReaderWriter> Call(
       ClientContext* context, const grpc::string& method, CompletionQueue* cq,
       void* tag);
diff --git a/include/grpc++/grpc++.h b/include/grpc++/grpc++.h
index daecfea..978b172 100644
--- a/include/grpc++/grpc++.h
+++ b/include/grpc++/grpc++.h
@@ -34,14 +34,18 @@
 /// \mainpage gRPC C++ API
 ///
 /// The gRPC C++ API mainly consists of the following classes:
+//
 /// - grpc::Channel, which represents the connection to an endpoint. See [the
 /// gRPC Concepts page](http://www.grpc.io/docs/guides/concepts.html) for more
 /// details. Channels are created by the factory function grpc::CreateChannel.
+//
 /// - grpc::CompletionQueue, the producer-consumer queue used for all
 /// asynchronous communication with the gRPC runtime.
+//
 /// - grpc::ClientContext and grpc::ServerContext, where optional configuration
 /// for an RPC can be set, such as setting custom metadata to be conveyed to the
 /// peer, compression settings, authentication, etc.
+//
 /// - grpc::Server, representing a gRPC server, created by grpc::ServerBuilder.
 ///
 /// Streaming calls are handled with the streaming classes in
diff --git a/include/grpc++/impl/codegen/async_stream.h b/include/grpc++/impl/codegen/async_stream.h
index 39f0ebd..5a685cb 100644
--- a/include/grpc++/impl/codegen/async_stream.h
+++ b/include/grpc++/impl/codegen/async_stream.h
@@ -58,11 +58,31 @@
   /// \param[in] tag Tag identifying this request.
   virtual void ReadInitialMetadata(void* tag) = 0;
 
-  /// Indicate that the stream is to be finished and request notification
-  /// Should not be used concurrently with other operations
+  /// Indicate that the stream is to be finished and request notification for
+  /// when the call has been ended.
+  /// Should not be used concurrently with other operations.
   ///
-  /// \param[out] status To be updated with the operation status.
+  /// It is appropriate to call this method when both:
+  ///   * the client side has no more message to send (this can be declared implicitly
+  ///     by calling this method, or explicitly through an earlier call to \a
+  ///     WritesDone.
+  ///   * there are no more messages to be received from the server (which can
+  ///     be known implicitly by the calling code, or known explicitly from an
+  ///     earlier call to \a Read that yielded a failed result
+  ///     (e.g. cq->Next(&read_tag, &ok) filled in 'ok' with 'false'.
+  ///
+  /// This function will return when either:
+  /// - all incoming messages have been read and the server has returned
+  ///   a status.
+  /// - the server has returned a non-OK status.
+  /// - the call failed for some reason and the library generated a
+  ///   status.
+  ///
+  /// Note that implementations of this method attempt to receive initial metadata
+  /// from the server if initial metadata hasn't yet been received.
+  ///
   /// \param[in] tag Tag identifying this request.
+  /// \param[out] status To be updated with the operation status.
   virtual void Finish(Status* status, void* tag) = 0;
 };
 
@@ -82,6 +102,9 @@
   ///
   /// \param[out] msg Where to eventually store the read message.
   /// \param[in] tag The tag identifying the operation.
+  ///
+  /// Side effect: note that this method attempt to receive initial metadata for a stream if it
+  /// hasn't yet been received.
   virtual void Read(R* msg, void* tag) = 0;
 };
 
@@ -140,10 +163,16 @@
 class ClientAsyncReaderInterface : public ClientAsyncStreamingInterface,
                                    public AsyncReaderInterface<R> {};
 
+/// Async client-side API for doing server-streaming RPCs,
+/// where the incoming message stream coming from the server has messages of type \a R.
 template <class R>
 class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
  public:
   /// Create a stream and write the first request out.
+  /// \a tag will be notified on \a cq when the call has been started and
+  /// \a request has been written out.
+  /// Note that \a context will be used to fill in custom initial metadata
+  /// used to send to the server when starting the call.
   template <class W>
   static ClientAsyncReader* Create(ChannelInterface* channel,
                                    CompletionQueue* cq, const RpcMethod& method,
@@ -155,11 +184,19 @@
         ClientAsyncReader(call, context, request, tag);
   }
 
-  /// always allocated against a call arena, no memory free required
+  // always allocated against a call arena, no memory free required
   static void operator delete(void* ptr, std::size_t size) {
     assert(size == sizeof(ClientAsyncReader));
   }
 
+  /// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata method for
+  /// semantics.
+  ///
+  /// Side effect:
+  ///   - upon receiving initial metadata from the server,
+  ///     the \a ClientContext associated with this call is updated, and the
+  ///     calling code can access the received metadata through the
+  ///     \a ClientContext.
   void ReadInitialMetadata(void* tag) override {
     GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
 
@@ -168,6 +205,7 @@
     call_.PerformOps(&meta_ops_);
   }
 
+  /// See the \a AsyncReaderInterface.Read method for semantics of this method.
   void Read(R* msg, void* tag) override {
     read_ops_.set_output_tag(tag);
     if (!context_->initial_metadata_received_) {
@@ -177,6 +215,11 @@
     call_.PerformOps(&read_ops_);
   }
 
+  /// See the \a ClientAsyncStreamingInterface.Finish method for semantics.
+  ///
+  /// Side effect:
+  ///   - the \a ClientContext associated with this call is updated with
+  ///     possible initial and trailing metadata received from the server.
   void Finish(Status* status, void* tag) override {
     finish_ops_.set_output_tag(tag);
     if (!context_->initial_metadata_received_) {
@@ -214,16 +257,26 @@
 class ClientAsyncWriterInterface : public ClientAsyncStreamingInterface,
                                    public AsyncWriterInterface<W> {
  public:
-  /// Signal the client is done with the writes.
+  /// Signal the client is done with the writes (half-close the client stream).
   /// Thread-safe with respect to \a Read
   ///
   /// \param[in] tag The tag identifying the operation.
   virtual void WritesDone(void* tag) = 0;
 };
 
+/// Async API to on the client side for doing client-streaming RPCs,
+/// where the outgoing message stream going to the server contains messages of type \a W.
 template <class W>
 class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
  public:
+  /// Create a stream and write the first request out.
+  /// \a tag will be notified on \a cq when the call has been started (i.e.
+  /// intitial metadata sent) and \a request has been written out.
+  /// Note that \a context will be used to fill in custom initial metadata
+  /// used to send to the server when starting the call.
+  /// \a response will be filled in with the single expected response
+  /// message from the server upon a successful call to the \a Finish
+  /// method of this instance.
   template <class R>
   static ClientAsyncWriter* Create(ChannelInterface* channel,
                                    CompletionQueue* cq, const RpcMethod& method,
@@ -235,11 +288,19 @@
         ClientAsyncWriter(call, context, response, tag);
   }
 
-  /// always allocated against a call arena, no memory free required
+  // always allocated against a call arena, no memory free required
   static void operator delete(void* ptr, std::size_t size) {
     assert(size == sizeof(ClientAsyncWriter));
   }
 
+  /// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata method for
+  /// semantics.
+  ///
+  /// Side effect:
+  ///   - upon receiving initial metadata from the server,
+  ///     the \a ClientContext associated with this call is updated, and the
+  ///     calling code can access the received metadata through the
+  ///     \a ClientContext.
   void ReadInitialMetadata(void* tag) override {
     GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
 
@@ -248,6 +309,8 @@
     call_.PerformOps(&meta_ops_);
   }
 
+  /// See the \a AsyncWriterInterface.Write(const W& msg, void* tag)
+  /// method for semantics of this method.
   void Write(const W& msg, void* tag) override {
     write_ops_.set_output_tag(tag);
     // TODO(ctiller): don't assert
@@ -255,6 +318,9 @@
     call_.PerformOps(&write_ops_);
   }
 
+  /// See the
+  /// \a AsyncWriterInterface.Write(const W& msg, WriteOptions options, void* tag)
+  /// method for semantics of this method.
   void Write(const W& msg, WriteOptions options, void* tag) override {
     write_ops_.set_output_tag(tag);
     if (options.is_last_message()) {
@@ -266,12 +332,21 @@
     call_.PerformOps(&write_ops_);
   }
 
+  /// See the \a ClientAsyncWriterInterface.WritesDone method for semantics of
+  /// this method.
   void WritesDone(void* tag) override {
     write_ops_.set_output_tag(tag);
     write_ops_.ClientSendClose();
     call_.PerformOps(&write_ops_);
   }
 
+  /// See the \a ClientAsyncStreamingInterface.Finish method for semantics.
+  ///
+  /// Side effect:
+  ///   - the \a ClientContext associated with this call is updated with
+  ///     possible initial and trailing metadata received from the server.
+  ///   - attempts to fill in the \a response parameter passed to this class's
+  ///     constructor with the server's response message.
   void Finish(Status* status, void* tag) override {
     finish_ops_.set_output_tag(tag);
     if (!context_->initial_metadata_received_) {
@@ -310,23 +385,33 @@
       finish_ops_;
 };
 
-/// Client-side interface for asynchronous bi-directional streaming.
+/// Async client-side interface for bi-directional streaming,
+/// where the client-to-server message stream has messages of type \a W,
+/// abnd the server-to-client message stream has messages of type \a R.
 template <class W, class R>
 class ClientAsyncReaderWriterInterface : public ClientAsyncStreamingInterface,
                                          public AsyncWriterInterface<W>,
                                          public AsyncReaderInterface<R> {
  public:
-  /// Signal the client is done with the writes.
+  /// Signal the client is done with the writes (half-close the client stream).
   /// Thread-safe with respect to \a Read
   ///
   /// \param[in] tag The tag identifying the operation.
   virtual void WritesDone(void* tag) = 0;
 };
 
+/// Async client-side interface for bi-directional streaming,
+/// where the outgoing message stream going to the server has messages of type \a W,
+/// and the incoming message stream coming from the server has messages of type \a R.
 template <class W, class R>
 class ClientAsyncReaderWriter final
     : public ClientAsyncReaderWriterInterface<W, R> {
  public:
+  /// Create a stream and write the first request out.
+  /// \a tag will be notified on \a cq when the call has been started (i.e.
+  /// intitial metadata sent).
+  /// Note that \a context will be used to fill in custom initial metadata
+  /// used to send to the server when starting the call.
   static ClientAsyncReaderWriter* Create(ChannelInterface* channel,
                                          CompletionQueue* cq,
                                          const RpcMethod& method,
@@ -338,11 +423,18 @@
         ClientAsyncReaderWriter(call, context, tag);
   }
 
-  /// always allocated against a call arena, no memory free required
+  // always allocated against a call arena, no memory free required
   static void operator delete(void* ptr, std::size_t size) {
     assert(size == sizeof(ClientAsyncReaderWriter));
   }
 
+  /// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata method
+  /// for semantics of this method.
+  ///
+  /// Side effect:
+  ///   - upon receiving initial metadata from the server, the \a ClientContext
+  ///     is updated with it, and then the receiving initial metadata can
+  ///     be accessed through this \a ClientContext
   void ReadInitialMetadata(void* tag) override {
     GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
 
@@ -351,6 +443,8 @@
     call_.PerformOps(&meta_ops_);
   }
 
+  /// See \a AsyncReaderInterface.Read method for semantics
+  /// of this method.
   void Read(R* msg, void* tag) override {
     read_ops_.set_output_tag(tag);
     if (!context_->initial_metadata_received_) {
@@ -360,6 +454,8 @@
     call_.PerformOps(&read_ops_);
   }
 
+  /// See \a AsyncWriterInterface.Write(const W& msg, void* tag) method for
+  /// semantics of this method.
   void Write(const W& msg, void* tag) override {
     write_ops_.set_output_tag(tag);
     // TODO(ctiller): don't assert
@@ -367,6 +463,8 @@
     call_.PerformOps(&write_ops_);
   }
 
+  /// See \a AsyncWriterInterface.Write(const W& msg, WriteOptions options, void* tag)
+  /// method for semantics of this method.
   void Write(const W& msg, WriteOptions options, void* tag) override {
     write_ops_.set_output_tag(tag);
     if (options.is_last_message()) {
@@ -378,12 +476,18 @@
     call_.PerformOps(&write_ops_);
   }
 
+  /// See \a ClientAsyncReaderWriterInterface.WritesDone method for semantics
+  /// of this method.
   void WritesDone(void* tag) override {
     write_ops_.set_output_tag(tag);
     write_ops_.ClientSendClose();
     call_.PerformOps(&write_ops_);
   }
 
+  /// See the \a ClientAsyncStreamingInterface.Finish method for semantics.
+  /// Side effect
+  ///   - the \a ClientContext associated with this call is updated with
+  ///     possible initial and trailing metadata sent from the server.
   void Finish(Status* status, void* tag) override {
     finish_ops_.set_output_tag(tag);
     if (!context_->initial_metadata_received_) {
@@ -422,17 +526,66 @@
 class ServerAsyncReaderInterface : public ServerAsyncStreamingInterface,
                                    public AsyncReaderInterface<R> {
  public:
+  /// Indicate that the stream is to be finished with a certain status code
+  /// and also send out \a msg response to the client.
+  /// Request notification for when the server has sent the response and the appropriate
+  /// signals to the client to end the call.
+  /// Should not be used concurrently with other operations.
+  ///
+  /// It is appropriate to call this method when:
+  ///   * all messages from the client have been received (either known
+  ///     implictly, or explicitly because a previous \a Read operation
+  ///     with a non-ok result (e.g., cq->Next(&read_tag, &ok) filled in 'ok'
+  ///     with 'false'.
+  ///
+  /// This operation will end when the server has finished sending out initial metadata
+  /// (if not sent already), repsonse message, and status, or if some failure
+  /// occurred when trying to do so.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[in] status To be sent to the client as the result of this call.
+  /// \param[in] msg To be sent to the client as the response for this call.
   virtual void Finish(const W& msg, const Status& status, void* tag) = 0;
 
+  /// Indicate that the stream is to be finished with a certain non-OK status code.
+  /// Request notification for when the server has sent the appropriate
+  /// signals to the client to end the call.
+  /// Should not be used concurrently with other operations.
+  ///
+  /// This call is meant to end the call with some error, and can be called at
+  /// any point that the server would like to "fail" the call (though note
+  /// this shouldn't be called concurrently with any other "sending" call, like
+  /// \a Write.
+  ///
+  /// This operation will end when the server has finished sending out initial metadata
+  /// (if not sent already), and status, or if some failure
+  /// occurred when trying to do so.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[in] status To be sent to the client as the result of this call.
+  ///     - Note: \a status must have a non-OK code.
   virtual void FinishWithError(const Status& status, void* tag) = 0;
 };
 
+/// Async server-side API for doing client-streaming RPCs,
+/// where the incoming message stream from the client has messages of type \a R,
+/// and the single response message sent from the server is type \a W.
 template <class W, class R>
 class ServerAsyncReader final : public ServerAsyncReaderInterface<W, R> {
  public:
   explicit ServerAsyncReader(ServerContext* ctx)
       : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
 
+  /// Request notification of the sending of initial metadata to the client. Completion
+  /// will be notified by \a tag on the associated completion queue.
+  /// This call is optional, but if it is used, it cannot be used concurrently
+  /// with or after the \a Finish method.
+  ///
+  /// Implicit input parameter:
+  ///   - The initial metadata that will be sent to the client from this op will be
+  ///     taken from the \a ServerContext associated with the call.
+  ///
+  /// \param[in] tag Tag identifying this request.
   void SendInitialMetadata(void* tag) override {
     GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 
@@ -446,12 +599,21 @@
     call_.PerformOps(&meta_ops_);
   }
 
+  /// See the \a AsyncReaderInterface.Read method for semantics.
   void Read(R* msg, void* tag) override {
     read_ops_.set_output_tag(tag);
     read_ops_.RecvMessage(msg);
     call_.PerformOps(&read_ops_);
   }
 
+  /// See the \a ServerAsyncReaderInterface.Read method for semantics
+  ///
+  /// Side effect:
+  ///   - also sends initial metadata if not alreay sent.
+  ///   - uses the \a ServerContext associated with this call to send possible
+  ///     initial and trailing metadata.
+  ///
+  /// Note: \a msg is not sent if \a status has a non-OK code.
   void Finish(const W& msg, const Status& status, void* tag) override {
     finish_ops_.set_output_tag(tag);
     if (!ctx_->sent_initial_metadata_) {
@@ -472,6 +634,12 @@
     call_.PerformOps(&finish_ops_);
   }
 
+  /// See the \a ServerAsyncReaderInterface.Read method for semantics
+  ///
+  /// Side effect:
+  ///   - also sends initial metadata if not alreay sent.
+  ///   - uses the \a ServerContext associated with this call to send possible
+  ///     initial and trailing metadata.
   void FinishWithError(const Status& status, void* tag) override {
     GPR_CODEGEN_ASSERT(!status.ok());
     finish_ops_.set_output_tag(tag);
@@ -503,6 +671,24 @@
 class ServerAsyncWriterInterface : public ServerAsyncStreamingInterface,
                                    public AsyncWriterInterface<W> {
  public:
+  /// Indicate that the stream is to be finished with a certain status code.
+  /// Request notification for when the server has sent the appropriate
+  /// signals to the client to end the call.
+  /// Should not be used concurrently with other operations.
+  ///
+  /// It is appropriate to call this method when either:
+  ///   * all messages from the client have been received (either known
+  ///     implictly, or explicitly because a previous \a Read operation
+  ///     with a non-ok result (e.g., cq->Next(&read_tag, &ok) filled in 'ok'
+  ///     with 'false'.
+  ///   * it is desired to end the call early with some non-OK status code.
+  ///
+  /// This operation will end when the server has finished sending out initial metadata
+  /// (if not sent already), repsonse message, and status, or if some failure
+  /// occurred when trying to do so.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[in] status To be sent to the client as the result of this call.
   virtual void Finish(const Status& status, void* tag) = 0;
 
   /// Request the writing of \a msg and coalesce it with trailing metadata which
@@ -520,12 +706,24 @@
                               const Status& status, void* tag) = 0;
 };
 
+/// Async server-side API for doing server streaming RPCs,
+/// where the outgoing message stream from the server has messages of type \a W.
 template <class W>
 class ServerAsyncWriter final : public ServerAsyncWriterInterface<W> {
  public:
   explicit ServerAsyncWriter(ServerContext* ctx)
       : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
 
+  /// Request notification of the sending the initial metadata to the client. Completion
+  /// will be notified by \a tag on the associated completion queue.
+  /// This call is optional, but if it is used, it cannot be used concurrently
+  /// with or after the \a Finish method.
+  ///
+  /// Implicit input parameter:
+  ///   - The initial metadata that will be sent to the client from this op will be
+  ///     taken from the \a ServerContext associated with the call.
+  ///
+  /// \param[in] tag Tag identifying this request.
   void SendInitialMetadata(void* tag) override {
     GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 
@@ -539,6 +737,7 @@
     call_.PerformOps(&meta_ops_);
   }
 
+  /// See the \a AsyncWriterInterface.Write(const W &msg, void *tag) method for semantics.
   void Write(const W& msg, void* tag) override {
     write_ops_.set_output_tag(tag);
     EnsureInitialMetadataSent(&write_ops_);
@@ -547,6 +746,7 @@
     call_.PerformOps(&write_ops_);
   }
 
+  /// See the \a AsyncWriterInterface.Write(const W &msg, WriteOptions options, void *tag) method for semantics.
   void Write(const W& msg, WriteOptions options, void* tag) override {
     write_ops_.set_output_tag(tag);
     if (options.is_last_message()) {
@@ -559,6 +759,13 @@
     call_.PerformOps(&write_ops_);
   }
 
+  /// See the \a ServerAsyncWriterInterface.WriteAndFinish method for semantics.
+  ///
+  /// Implicit input parameter:
+  ///   - the \a ServerContext associated with this call is used
+  ///     for sending trailing (and initial) metadata to the client.
+  ///
+  /// Note: \a status must have an OK code.
   void WriteAndFinish(const W& msg, WriteOptions options, const Status& status,
                       void* tag) override {
     write_ops_.set_output_tag(tag);
@@ -569,6 +776,13 @@
     call_.PerformOps(&write_ops_);
   }
 
+  /// See the \a ServerAsyncWriterInterface.Finish method for semantics.
+  ///
+  /// Implicit input parameter:
+  ///   - the \a ServerContext associated with this call is used
+  ///     for sending trailing (and initial if not already sent) metadata to the client.
+  ///
+  /// Note: there are no restrictions are the code of \a status, it may be non-OK
   void Finish(const Status& status, void* tag) override {
     finish_ops_.set_output_tag(tag);
     EnsureInitialMetadataSent(&finish_ops_);
@@ -606,6 +820,24 @@
                                          public AsyncWriterInterface<W>,
                                          public AsyncReaderInterface<R> {
  public:
+  /// Indicate that the stream is to be finished with a certain status code.
+  /// Request notification for when the server has sent the appropriate
+  /// signals to the client to end the call.
+  /// Should not be used concurrently with other operations.
+  ///
+  /// It is appropriate to call this method when either:
+  ///   * all messages from the client have been received (either known
+  ///     implictly, or explicitly because a previous \a Read operation
+  ///     with a non-ok result (e.g., cq->Next(&read_tag, &ok) filled in 'ok'
+  ///     with 'false'.
+  ///   * it is desired to end the call early with some non-OK status code.
+  ///
+  /// This operation will end when the server has finished sending out initial metadata
+  /// (if not sent already), repsonse message, and status, or if some failure
+  /// occurred when trying to do so.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[in] status To be sent to the client as the result of this call.
   virtual void Finish(const Status& status, void* tag) = 0;
 
   /// Request the writing of \a msg and coalesce it with trailing metadata which
@@ -623,6 +855,9 @@
                               const Status& status, void* tag) = 0;
 };
 
+/// Async server-side API for doing bidirectional streaming RPCs,
+/// where the incoming message stream coming from the client has messages of type \a R,
+/// and the outgoing message stream coming from the server has messages of type \a W.
 template <class W, class R>
 class ServerAsyncReaderWriter final
     : public ServerAsyncReaderWriterInterface<W, R> {
@@ -630,6 +865,16 @@
   explicit ServerAsyncReaderWriter(ServerContext* ctx)
       : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
 
+  /// Request notification of the sending the initial metadata to the client. Completion
+  /// will be notified by \a tag on the associated completion queue.
+  /// This call is optional, but if it is used, it cannot be used concurrently
+  /// with or after the \a Finish method.
+  ///
+  /// Implicit input parameter:
+  ///   - The initial metadata that will be sent to the client from this op will be
+  ///     taken from the \a ServerContext associated with the call.
+  ///
+  /// \param[in] tag Tag identifying this request.
   void SendInitialMetadata(void* tag) override {
     GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 
@@ -643,12 +888,14 @@
     call_.PerformOps(&meta_ops_);
   }
 
+  /// See the \a AsyncReaderInterface.Read method for semantics.
   void Read(R* msg, void* tag) override {
     read_ops_.set_output_tag(tag);
     read_ops_.RecvMessage(msg);
     call_.PerformOps(&read_ops_);
   }
 
+  /// See the \a AsyncWriterInterface.Write(const W& msg, void* tag) method for semantics.
   void Write(const W& msg, void* tag) override {
     write_ops_.set_output_tag(tag);
     EnsureInitialMetadataSent(&write_ops_);
@@ -657,6 +904,7 @@
     call_.PerformOps(&write_ops_);
   }
 
+  /// See the \a AsyncWriterInterface.Write(const W& msg, WriteOptions options, void* tag) method for semantics.
   void Write(const W& msg, WriteOptions options, void* tag) override {
     write_ops_.set_output_tag(tag);
     if (options.is_last_message()) {
@@ -667,6 +915,13 @@
     call_.PerformOps(&write_ops_);
   }
 
+  /// See the \a ServerAsyncReaderWriterInterface.WriteAndFinish method for semantics.
+  ///
+  /// Implicit input parameter:
+  ///   - the \a ServerContext associated with this call is used
+  ///     for sending trailing (and initial) metadata to the client.
+  ///
+  /// Note: \a status must have an OK code.
   void WriteAndFinish(const W& msg, WriteOptions options, const Status& status,
                       void* tag) override {
     write_ops_.set_output_tag(tag);
@@ -677,6 +932,13 @@
     call_.PerformOps(&write_ops_);
   }
 
+  /// See the \a ServerAsyncReaderWriterInterface.Finish method for semantics.
+  ///
+  /// Implicit input parameter:
+  ///   - the \a ServerContext associated with this call is used
+  ///     for sending trailing (and initial if not already sent) metadata to the client.
+  ///
+  /// Note: there are no restrictions are the code of \a status, it may be non-OK
   void Finish(const Status& status, void* tag) override {
     finish_ops_.set_output_tag(tag);
     EnsureInitialMetadataSent(&finish_ops_);
diff --git a/include/grpc++/impl/codegen/async_unary_call.h b/include/grpc++/impl/codegen/async_unary_call.h
index ea2da42..15179e5 100644
--- a/include/grpc++/impl/codegen/async_unary_call.h
+++ b/include/grpc++/impl/codegen/async_unary_call.h
@@ -55,10 +55,17 @@
   virtual void Finish(R* msg, Status* status, void* tag) = 0;
 };
 
+/// Async API for client-side unary RPCs, where the message response
+/// received from the server is of type \a R.
 template <class R>
 class ClientAsyncResponseReader final
     : public ClientAsyncResponseReaderInterface<R> {
  public:
+  /// Start a call and write the request out.
+  /// \a tag will be notified on \a cq when the call has been started (i.e.
+  /// intitial metadata sent) and \a request has been written out.
+  /// Note that \a context will be used to fill in custom initial metadata
+  /// used to send to the server when starting the call.
   template <class W>
   static ClientAsyncResponseReader* Create(ChannelInterface* channel,
                                            CompletionQueue* cq,
@@ -71,11 +78,24 @@
         ClientAsyncResponseReader(call, context, request);
   }
 
-  /// always allocated against a call arena, no memory free required
+  // always allocated against a call arena, no memory free required
   static void operator delete(void* ptr, std::size_t size) {
     assert(size == sizeof(ClientAsyncResponseReader));
   }
 
+  /// Request notification of the reading of initial metadata. Completion
+  /// will be notified by \a tag on the associated completion queue.
+  /// This call is optional, but if it is used, it cannot be used concurrently
+  /// with or after the \a Finish method.
+  ///
+  /// Once a completion has been notified, the initial metadata read from
+  /// the server will be accessable through the \a ClientContext used to
+  /// construct this object.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// Side effect:
+  ///   - the \a ClientContext associated with this call is updated with
+  ///     possible initial and trailing metadata sent from the serve.
   void ReadInitialMetadata(void* tag) {
     GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
 
@@ -84,6 +104,24 @@
     call_.PerformOps(&meta_buf_);
   }
 
+  /// Request to receive the server's response \a msg and final \a status for
+  /// the call, and to notify \a tag on this call's completion queue when
+  /// finished.
+  ///
+  /// This function will return when either:
+  /// - when the server's response message and status have been received.
+  /// - when the server has returned a non-OK status (no message expected in
+  ///   this case).
+  /// - when the call failed for some reason and the library generated a
+  ///   non-OK status.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[out] status To be updated with the operation status.
+  /// \param[out] msg To be filled in with the server's response message.
+  ///
+  /// Side effect:
+  ///   - the \a ClientContext associated with this call is updated with
+  ///     possible initial and trailing metadata sent from the server.
   void Finish(R* msg, Status* status, void* tag) {
     finish_buf_.set_output_tag(tag);
     if (!context_->initial_metadata_received_) {
@@ -123,12 +161,23 @@
       finish_buf_;
 };
 
+/// Async server-side API for handling unary calls, where the single
+/// response message sent to the client is of type \a W.
 template <class W>
 class ServerAsyncResponseWriter final : public ServerAsyncStreamingInterface {
  public:
   explicit ServerAsyncResponseWriter(ServerContext* ctx)
       : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
 
+  /// Request notification of the sending the initial metadata to the client. Completion
+  /// will be notified by \a tag on the associated completion queue.
+  /// This call is optional, but if it is used, it cannot be used concurrently
+  /// with or after the \a Finish method.
+  ///
+  /// The initial metadata that will be sent to the client from this op will be
+  /// taken from the \a ServerContext associated with the call.
+  ///
+  /// \param[in] tag Tag identifying this request.
   void SendInitialMetadata(void* tag) override {
     GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 
@@ -142,6 +191,21 @@
     call_.PerformOps(&meta_buf_);
   }
 
+  /// Indicate that the stream is to be finished and request notification
+  /// when the server has sent the appropriate signals to the client to
+  /// end the call.
+  /// Should not be used concurrently with other operations.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[in] status To be sent to the client as the result of the call.
+  /// \param[in] msg Message to be sent to the client.
+  /// Side effect:
+  ///   - also sends initial metadata if not already sent (using the
+  ///     \a ServerContext associated with this call).
+  ///
+  /// Note: if \a status has a non-OK code, then \a msg will not be sent,
+  /// and the client will receive only the status with possible trailing
+  /// metadata.
   void Finish(const W& msg, const Status& status, void* tag) {
     finish_buf_.set_output_tag(tag);
     if (!ctx_->sent_initial_metadata_) {
@@ -162,6 +226,17 @@
     call_.PerformOps(&finish_buf_);
   }
 
+  /// Indicate that the stream is to be finished with a non-OK status,
+  /// and request notification for when the server has finished sending the
+  /// appropriate signals to the client to end the call.
+  /// Should not be used concurrently with other operations.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[in] status To be sent to the client as the result of the call.
+  ///   - Note: \a status must have a non-OK code.
+  /// Side effect:
+  ///   - also sends initial metadata if not already sent (using the
+  ///     \a ServerContext associated with this call).
   void FinishWithError(const Status& status, void* tag) {
     GPR_CODEGEN_ASSERT(!status.ok());
     finish_buf_.set_output_tag(tag);
diff --git a/include/grpc++/impl/codegen/call_hook.h b/include/grpc++/impl/codegen/call_hook.h
index 812c4a9..85a5f86 100644
--- a/include/grpc++/impl/codegen/call_hook.h
+++ b/include/grpc++/impl/codegen/call_hook.h
@@ -39,8 +39,8 @@
 class CallOpSetInterface;
 class Call;
 
-/// An interface that Channel and Server implement to allow them to hook
-/// performing ops
+/// This is an interface that Channel and Server implement to allow them to hook
+/// performing ops.
 class CallHook {
  public:
   virtual ~CallHook() {}
diff --git a/include/grpc++/impl/codegen/client_context.h b/include/grpc++/impl/codegen/client_context.h
index c17ce20..31bd0d2 100644
--- a/include/grpc++/impl/codegen/client_context.h
+++ b/include/grpc++/impl/codegen/client_context.h
@@ -151,7 +151,20 @@
 class InteropClientContextInspector;
 }  // namespace testing
 
-/// Gives access to client side RPC configuration.
+/// A ClientContext allows the person implementing a service client to:
+///
+/// - Add custom metadata key-value pairs that will propagated to the server
+/// side.
+/// - Control call settings such as compression and authentication.
+/// - Initial and trailing metadata coming from the server.
+/// - Get performance metrics (ie, census).
+///
+/// Context settings are only relevant to the call they are invoked with, that
+/// is to say, they aren't sticky. Some of these settings, such as the
+/// compression options, can be made persistant at channel construction time
+/// (see \a grpc::CreateCustomChannel).
+///
+/// \warning ClientContext instances should \em not be reused across rpcs.
 class ClientContext {
  public:
   ClientContext();
@@ -223,13 +236,24 @@
     deadline_ = deadline_tp.raw_time();
   }
 
-  /// EXPERIMENTAL: Set this request to be idempotent
+  /// EXPERIMENTAL: Indicate that this request is idempotent.
+  /// By default, RPCs are assumed to <i>not</i> be idempotent.
+  ///
+  /// If true, the gRPC library assumes that it's safe to initiate
+  /// this RPC multiple times.
   void set_idempotent(bool idempotent) { idempotent_ = idempotent; }
 
   /// EXPERIMENTAL: Set this request to be cacheable
+  /// If set, grpc is free the GET verb for sending the request,
+  /// with the possibility of receiving a cached respone.
   void set_cacheable(bool cacheable) { cacheable_ = cacheable; }
 
   /// EXPERIMENTAL: Trigger wait-for-ready or not on this request
+  /// See grpc/doc/wait-for-ready.md.
+  /// If set, if an RPC made when a channel's connectivity state is
+  /// TRANSIENT_FAILURE or CONNECTING, the call will not "fail fast",
+  /// and the channel will wait until the channel is READY before making the
+  /// call.
   void set_wait_for_ready(bool wait_for_ready) {
     wait_for_ready_ = wait_for_ready;
     wait_for_ready_explicitly_set_ = true;
diff --git a/include/grpc++/impl/codegen/server_context.h b/include/grpc++/impl/codegen/server_context.h
index 07e3710..beaad1c 100644
--- a/include/grpc++/impl/codegen/server_context.h
+++ b/include/grpc++/impl/codegen/server_context.h
@@ -91,63 +91,129 @@
 class ServerContextTestSpouse;
 }  // namespace testing
 
-/// Interface of server side rpc context.
+/// A ServerContext allows the person implementing a service handler to:
+///
+/// - Add custom initial and trailing metadata key-value pairs that will propagated
+///   to the client side.
+/// - Control call settings such as compression and authentication.
+/// - Access Initial metadata coming from the client.
+/// - Get performance metrics (ie, census).
+///
+/// Context settings are only relevant to the call handler they are supplied to, that
+/// is to say, they aren't sticky across multiple calls. Some of these settings,
+/// such as the compression options, can be made persistant at server construction time
+/// by specifying the approriate \a ChannelArguments parameter to the see \a grpc::Server
+/// constructor.
+///
+/// \warning ServerContext instances should \em not be reused across rpcs.
 class ServerContext {
  public:
   ServerContext();  // for async calls
   ~ServerContext();
 
+  /// Return the deadline for the server call.
   std::chrono::system_clock::time_point deadline() const {
     return Timespec2Timepoint(deadline_);
   }
 
+  /// Return a \a gpr_timespec representation of the server call's deadline.
   gpr_timespec raw_deadline() const { return deadline_; }
 
+  /// Add the (\a meta_key, \a meta_value) pair to the initial metadata associated with
+  /// a server call. These are made available at the client side by the \a
+  /// grpc::ClientContext::GetServerInitialMetadata() method.
+  ///
+  /// \warning This method should only be called before sending initial metadata
+  /// to the client (which can happen explicitly, or implicitly when sending a
+  /// a response message or status to the client).
+  ///
+  /// \param meta_key The metadata key. If \a meta_value is binary data, it must
+  /// end in "-bin".
+  /// \param meta_value The metadata value. If its value is binary, it must be
+  /// base64-encoding (see https://tools.ietf.org/html/rfc4648#section-4) and \a
+  /// meta_key must end in "-bin".
   void AddInitialMetadata(const grpc::string& key, const grpc::string& value);
+
+  /// Add the (\a meta_key, \a meta_value) pair to the initial metadata associated with
+  /// a server call. These are made available at the client side by the \a
+  /// grpc::ClientContext::GetServerTrailingMetadata() method.
+  ///
+  /// \warning This method should only be called before sending trailing metadata
+  /// to the client (which happens when the call is finished and a status is
+  /// sent to the client).
+  ///
+  /// \param meta_key The metadata key. If \a meta_value is binary data, it must
+  /// end in "-bin".
+  /// \param meta_value The metadata value. If its value is binary, it must be
+  /// base64-encoding (see https://tools.ietf.org/html/rfc4648#section-4) and \a
+  /// meta_key must end in "-bin".
   void AddTrailingMetadata(const grpc::string& key, const grpc::string& value);
 
-  /// IsCancelled is always safe to call when using sync API
+  /// IsCancelled is always safe to call when using sync API.
   /// When using async API, it is only safe to call IsCancelled after
-  /// the AsyncNotifyWhenDone tag has been delivered
+  /// the AsyncNotifyWhenDone tag has been delivered.
   bool IsCancelled() const;
 
-  // Cancel the Call from the server. This is a best-effort API and depending on
-  // when it is called, the RPC may still appear successful to the client.
-  // For example, if TryCancel() is called on a separate thread, it might race
-  // with the server handler which might return success to the client before
-  // TryCancel() was even started by the thread.
-  //
-  // It is the caller's responsibility to prevent such races and ensure that if
-  // TryCancel() is called, the serverhandler must return Status::CANCELLED. The
-  // only exception is that if the serverhandler is already returning an error
-  // status code, it is ok to not return Status::CANCELLED even if TryCancel()
-  // was called.
+  /// Cancel the Call from the server. This is a best-effort API and depending on
+  /// when it is called, the RPC may still appear successful to the client.
+  /// For example, if TryCancel() is called on a separate thread, it might race
+  /// with the server handler which might return success to the client before
+  /// TryCancel() was even started by the thread.
+  ///
+  /// It is the caller's responsibility to prevent such races and ensure that if
+  /// TryCancel() is called, the serverhandler must return Status::CANCELLED. The
+  /// only exception is that if the serverhandler is already returning an error
+  /// status code, it is ok to not return Status::CANCELLED even if TryCancel()
+  /// was called.
   void TryCancel() const;
 
+  /// Return a collection of initial metadata key-value pairs sent from the
+  /// client. Note that keys
+  /// may happen more than once (ie, a \a std::multimap is returned).
+  ///
+  /// It is safe to use this method after initial metadata has been received,
+  /// Calls always begin with the client sending initial metadata, so this is
+  /// safe to access as soon as the call has begun on the server side.
+  ///
+  /// \return A multimap of initial metadata key-value pairs from the server.
   const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata()
       const {
     return *client_metadata_.map();
   }
 
+  /// Return the compression algorithm to be used by the server call.
   grpc_compression_level compression_level() const {
     return compression_level_;
   }
 
+  /// Set \a algorithm to be the compression algorithm used for the server call.
+  ///
+  /// \param algorithm The compression algorithm used for the server call.
   void set_compression_level(grpc_compression_level level) {
     compression_level_set_ = true;
     compression_level_ = level;
   }
 
+  /// Return a bool indicating whether the compression level for this call
+  /// has been set (either implicitly or through a previous call to
+  /// \a set_compression_level
   bool compression_level_set() const { return compression_level_set_; }
 
+  /// Return the compression algorithm to be used by the server call.
   grpc_compression_algorithm compression_algorithm() const {
     return compression_algorithm_;
   }
+  /// Set \a algorithm to be the compression algorithm used for the server call.
+  ///
+  /// \param algorithm The compression algorithm used for the server call.
   void set_compression_algorithm(grpc_compression_algorithm algorithm);
 
-  // Set the load reporting costs in \a cost_data for the call.
+  /// Set the load reporting costs in \a cost_data for the call.
   void SetLoadReportingCosts(const std::vector<grpc::string>& cost_data);
 
+  /// Return the authentication context for this server call.
+  ///
+  /// \see grpc::AuthContext.
   std::shared_ptr<const AuthContext> auth_context() const {
     if (auth_context_.get() == nullptr) {
       auth_context_ = CreateAuthContext(call_);
@@ -155,24 +221,25 @@
     return auth_context_;
   }
 
-  // Return the peer uri in a string.
-  // WARNING: this value is never authenticated or subject to any security
-  // related code. It must not be used for any authentication related
-  // functionality. Instead, use auth_context.
+  /// Return the peer uri in a string.
+  /// WARNING: this value is never authenticated or subject to any security
+  /// related code. It must not be used for any authentication related
+  /// functionality. Instead, use auth_context.
   grpc::string peer() const;
 
+  /// Get the census context associated with this server call.
   const struct census_context* census_context() const;
 
-  // Async only. Has to be called before the rpc starts.
-  // Returns the tag in completion queue when the rpc finishes.
-  // IsCancelled() can then be called to check whether the rpc was cancelled.
+  /// Async only. Has to be called before the rpc starts.
+  /// Returns the tag in completion queue when the rpc finishes.
+  /// IsCancelled() can then be called to check whether the rpc was cancelled.
   void AsyncNotifyWhenDone(void* tag) {
     has_notify_when_done_tag_ = true;
     async_notify_when_done_tag_ = tag;
   }
 
-  // Should be used for framework-level extensions only.
-  // Applications never need to call this method.
+  /// Should be used for framework-level extensions only.
+  /// Applications never need to call this method.
   grpc_call* c_call() { return call_; }
 
  private:
@@ -205,14 +272,14 @@
   friend class UnknownMethodHandler;
   friend class ::grpc::ClientContext;
 
-  // Prevent copying.
+  /// Prevent copying.
   ServerContext(const ServerContext&);
   ServerContext& operator=(const ServerContext&);
 
   class CompletionOp;
 
   void BeginCompletionOp(Call* call);
-  // Return the tag queued by BeginCompletionOp()
+  /// Return the tag queued by BeginCompletionOp()
   CompletionQueueTag* GetCompletionOpTag();
 
   ServerContext(gpr_timespec deadline, grpc_metadata_array* arr);
diff --git a/include/grpc++/impl/codegen/status_code_enum.h b/include/grpc++/impl/codegen/status_code_enum.h
index 2eb97e8..a60cdef 100644
--- a/include/grpc++/impl/codegen/status_code_enum.h
+++ b/include/grpc++/impl/codegen/status_code_enum.h
@@ -141,7 +141,6 @@
   /// anything. So in general it is unsafe to retry on this status code
   /// if the call is non-idempotent.
   ///
-  ///
   /// See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,
   /// and UNAVAILABLE.
   UNAVAILABLE = 14,
diff --git a/include/grpc++/impl/codegen/sync_stream.h b/include/grpc++/impl/codegen/sync_stream.h
index 34b814e..ecde15f 100644
--- a/include/grpc++/impl/codegen/sync_stream.h
+++ b/include/grpc++/impl/codegen/sync_stream.h
@@ -50,16 +50,28 @@
  public:
   virtual ~ClientStreamingInterface() {}
 
-  /// Wait until the stream finishes, and return the final status. When the
-  /// client side declares it has no more message to send, either implicitly or
-  /// by calling \a WritesDone(), it needs to make sure there is no more message
-  /// to be received from the server, either implicitly or by getting a false
-  /// from a \a Read().
+  /// Block waiting until the stream finishes and a final status of the call is
+  /// available.
+  ///
+  /// It is appropriate to call this method when both:
+  ///   * the calling code (client-side) has no more message to send (this can be declared implicitly
+  ///     by calling this method, or explicitly through an earlier call to \a
+  ///     WritesDone.
+  ///   * there are no more messages to be received from the server (which can
+  ///     be known implicitly, or explicitly from an earlier call to \a Read that
+  ///     returned "false"
   ///
   /// This function will return either:
   /// - when all incoming messages have been read and the server has returned
   ///   status.
-  /// - OR when the server has returned a non-OK status.
+  /// - when the server has returned a non-OK status.
+  /// - OR when the call failed for some reason and the library generated a
+  ///   status.
+  ///
+  /// Return values:
+  ///   - \a Status contains the status code, message and details for the call
+  ///   - the \a ClientContext associated with this call is updated with
+  ///     possible trailing metadata sent from the server.
   virtual Status Finish() = 0;
 };
 
@@ -68,7 +80,12 @@
  public:
   virtual ~ServerStreamingInterface() {}
 
-  /// Blocking send initial metadata to client.
+  /// Block to send initial metadata to client.
+  /// This call is optional, but if it is used, it cannot be used concurrently
+  /// with or after the \a Finish method.
+  ///
+  /// The initial metadata that will be sent to the client will be
+  /// taken from the \a ServerContext associated with the call.
   virtual void SendInitialMetadata() = 0;
 };
 
@@ -78,10 +95,10 @@
  public:
   virtual ~ReaderInterface() {}
 
-  /// Upper bound on the next message size available for reading on this stream
+  /// Get an upper bound on the next message size available for reading on this stream.
   virtual bool NextMessageSize(uint32_t* sz) = 0;
 
-  /// Blocking read a message and parse to \a msg. Returns \a true on success.
+  /// Block to read a message and parse to \a msg. Returns \a true on success.
   /// This is thread-safe with respect to \a Write or \WritesDone methods on
   /// the same stream. It should not be called concurrently with another \a
   /// Read on the same stream as the order of delivery will not be defined.
@@ -100,7 +117,7 @@
  public:
   virtual ~WriterInterface() {}
 
-  /// Blocking write \a msg to the stream with WriteOptions \a options.
+  /// Block to write \a msg to the stream with WriteOptions \a options.
   /// This is thread-safe with respect to \a Read
   ///
   /// \param msg The message to be written to the stream.
@@ -109,7 +126,7 @@
   /// \return \a true on success, \a false when the stream has been closed.
   virtual bool Write(const W& msg, WriteOptions options) = 0;
 
-  /// Blocking write \a msg to the stream with default write options.
+  /// Block to write \a msg to the stream with default write options.
   /// This is thread-safe with respect to \a Read
   ///
   /// \param msg The message to be written to the stream.
@@ -141,17 +158,21 @@
 class ClientReaderInterface : public ClientStreamingInterface,
                               public ReaderInterface<R> {
  public:
-  /// Blocking wait for initial metadata from server. The received metadata
+  /// Block to wait for initial metadata from server. The received metadata
   /// can only be accessed after this call returns. Should only be called before
   /// the first read. Calling this method is optional, and if it is not called
   /// the metadata will be available in ClientContext after the first read.
   virtual void WaitForInitialMetadata() = 0;
 };
 
+/// Synchronous (blocking) client-side API for doing server-streaming RPCs, where the
+/// stream of messages coming from the server has messages of type \a R.
 template <class R>
 class ClientReader final : public ClientReaderInterface<R> {
  public:
-  /// Blocking create a stream and write the first request out.
+  /// Block to create a stream and write the initial metadata and \a request out.
+  /// Note that \a context will be used to fill in custom initial metadata
+  /// used to send to the server when starting the call.
   template <class W>
   ClientReader(ChannelInterface* channel, const RpcMethod& method,
                ClientContext* context, const W& request)
@@ -172,6 +193,13 @@
     cq_.Pluck(&ops);
   }
 
+  /// See the \a ClientStreamingInterface.WaitForInitialMetadata method for
+  /// semantics.
+  ///
+  //  Side effect:
+  ///   Once complete, the initial metadata read from
+  ///   the server will be accessable through the \a ClientContext used to
+  ///   construct this object.
   void WaitForInitialMetadata() override {
     GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
 
@@ -181,11 +209,17 @@
     cq_.Pluck(&ops);  /// status ignored
   }
 
+  /// See the \a ReaderInterface.NextMessageSize for semantics.
   bool NextMessageSize(uint32_t* sz) override {
     *sz = call_.max_receive_message_size();
     return true;
   }
 
+  /// See the \a ReaderInterface.Read method for semantics.
+  /// Side effect:
+  ///   this also receives initial metadata from the server, if not
+  ///   already received (if initial metadata is received, it can be then accessed
+  ///   through the \a ClientContext associated with this call).
   bool Read(R* msg) override {
     CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> ops;
     if (!context_->initial_metadata_received_) {
@@ -196,6 +230,11 @@
     return cq_.Pluck(&ops) && ops.got_message;
   }
 
+  /// See the \a ClientStreamingInterface.Finish method for semantics.
+  ///
+  /// Side effect:
+  ///   - the \a ClientContext associated with this call is updated with
+  ///     possible metadata received from the server.
   Status Finish() override {
     CallOpSet<CallOpClientRecvStatus> ops;
     Status status;
@@ -211,23 +250,30 @@
   Call call_;
 };
 
-/// Client-side interface for streaming writes of message of type \a W.
+/// Client-side interface for streaming writes of message type \a W.
 template <class W>
 class ClientWriterInterface : public ClientStreamingInterface,
                               public WriterInterface<W> {
  public:
-  /// Half close writing from the client.
-  /// Block until currently-pending writes are completed.
+  /// Half close writing from the client. (signal that the stream of messages
+  /// coming from the clinet is complete).
+  /// Blocks until currently-pending writes are completed.
   /// Thread safe with respect to \a Read operations only
   ///
   /// \return Whether the writes were successful.
   virtual bool WritesDone() = 0;
 };
 
+/// Synchronous (blocking) client-side API for doing client-streaming RPCs,
+/// where the outgoing message stream coming from the client has messages of type \a W.
 template <class W>
 class ClientWriter : public ClientWriterInterface<W> {
  public:
-  /// Blocking create a stream.
+  /// Block to create a stream (i.e. send request headers and other initial metadata to the server).
+  /// Note that \a context will be used to fill in custom initial metadata.
+  /// \a response will be filled in with the single expected response
+  /// message from the server upon a successful call to the \a Finish
+  /// method of this instance.
   template <class R>
   ClientWriter(ChannelInterface* channel, const RpcMethod& method,
                ClientContext* context, R* response)
@@ -248,6 +294,13 @@
     }
   }
 
+  /// See the \a ClientStreamingInterface.WaitForInitialMetadata method for
+  /// semantics.
+  ///
+  //  Side effect:
+  ///   Once complete, the initial metadata read from
+  ///   the server will be accessable through the \a ClientContext used to
+  ///   construct this object.
   void WaitForInitialMetadata() {
     GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
 
@@ -257,6 +310,12 @@
     cq_.Pluck(&ops);  // status ignored
   }
 
+  /// See the WriterInterface.Write(const W& msg, WriteOptions options) method
+  /// for semantics.
+  ///
+  /// Side effect:
+  ///   Also sends initial metadata if not already sent (using the \a ClientContext
+  ///   associated with this call).
   using WriterInterface<W>::Write;
   bool Write(const W& msg, WriteOptions options) override {
     CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
@@ -280,6 +339,7 @@
     return cq_.Pluck(&ops);
   }
 
+  /// See the \a ClientWriterInterface.WritesDone method for semantics.
   bool WritesDone() override {
     CallOpSet<CallOpClientSendClose> ops;
     ops.ClientSendClose();
@@ -287,7 +347,11 @@
     return cq_.Pluck(&ops);
   }
 
-  /// Read the final response and wait for the final status.
+  /// See the ClientStreamingInterface.Finish method for semantics.
+  /// Side effects:
+  ///   - Also receives initial metadata if not already received.
+  ///   - Attempts to fill in the \a response parameter passed to the constructor
+  ///     of this instance with the response message from the server.
   Status Finish() override {
     Status status;
     if (!context_->initial_metadata_received_) {
@@ -308,29 +372,39 @@
   Call call_;
 };
 
-/// Client-side interface for bi-directional streaming.
+/// Client-side interface for bi-directional streaming with
+/// client-to-server stream messages of type \a W and
+/// server-to-client stream messages of type \a R.
 template <class W, class R>
 class ClientReaderWriterInterface : public ClientStreamingInterface,
                                     public WriterInterface<W>,
                                     public ReaderInterface<R> {
  public:
-  /// Blocking wait for initial metadata from server. The received metadata
+  /// Block to wait for initial metadata from server. The received metadata
   /// can only be accessed after this call returns. Should only be called before
   /// the first read. Calling this method is optional, and if it is not called
   /// the metadata will be available in ClientContext after the first read.
   virtual void WaitForInitialMetadata() = 0;
 
-  /// Block until currently-pending writes are completed.
+  /// Half close writing from the client. (signal that the stream of messages
+  /// coming from the clinet is complete).
+  /// Blocks until currently-pending writes are completed.
   /// Thread-safe with respect to \a Read
   ///
   /// \return Whether the writes were successful.
   virtual bool WritesDone() = 0;
 };
 
+/// Synchronous (blocking) client-side API for bi-directional streaming RPCs, where the
+/// outgoing message stream coming from the client has messages of type \a W,
+/// and the incoming messages stream coming from the server has messages of type
+/// \a R.
 template <class W, class R>
 class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
  public:
-  /// Blocking create a stream.
+  /// Block to create a stream and write the initial metadata and \a request out.
+  /// Note that \a context will be used to fill in custom initial metadata
+  /// used to send to the server when starting the call.
   ClientReaderWriter(ChannelInterface* channel, const RpcMethod& method,
                      ClientContext* context)
       : context_(context),
@@ -347,6 +421,13 @@
     }
   }
 
+  /// Block waiting to read initial metadata from the server.
+  /// This call is optional, but if it is used, it cannot be used concurrently
+  /// with or after the \a Finish method.
+  ///
+  /// Once complete, the initial metadata read from
+  /// the server will be accessable through the \a ClientContext used to
+  /// construct this object.
   void WaitForInitialMetadata() override {
     GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
 
@@ -361,6 +442,10 @@
     return true;
   }
 
+  /// See the \a ReaderInterface.Read method for semantics.
+  /// Side effect:
+  ///   Also receives initial metadata if not already received (updates the \a
+  ///   ClientContext associated with this call in that case).
   bool Read(R* msg) override {
     CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> ops;
     if (!context_->initial_metadata_received_) {
@@ -371,6 +456,11 @@
     return cq_.Pluck(&ops) && ops.got_message;
   }
 
+  /// See the \a WriterInterface.Write method for semantics.
+  ///
+  /// Side effect:
+  ///   Also sends initial metadata if not already sent (using the
+  ///   \a ClientContext associated with this call to fill in values).
   using WriterInterface<W>::Write;
   bool Write(const W& msg, WriteOptions options) override {
     CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
@@ -394,6 +484,7 @@
     return cq_.Pluck(&ops);
   }
 
+  /// See the ClientWriterInterface.WritesDone method for semantics.
   bool WritesDone() override {
     CallOpSet<CallOpClientSendClose> ops;
     ops.ClientSendClose();
@@ -401,6 +492,11 @@
     return cq_.Pluck(&ops);
   }
 
+  /// See the ClientStreamingInterface.Finish method for semantics.
+  ///
+  /// Side effect:
+  ///   - the \a ClientContext associated with this call is updated with
+  ///     possible trailing metadata sent from the server.
   Status Finish() override {
     CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> ops;
     if (!context_->initial_metadata_received_) {
@@ -424,11 +520,18 @@
 class ServerReaderInterface : public ServerStreamingInterface,
                               public ReaderInterface<R> {};
 
+/// Synchronous (blocking) server-side API for doing client-streaming RPCs,
+/// where the incoming message stream coming from the client has messages of
+/// type \a R.
 template <class R>
 class ServerReader final : public ServerReaderInterface<R> {
  public:
   ServerReader(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
 
+  /// See the \a ServerStreamingInterface.SendInitialMetadata method
+  /// for semantics.
+  /// Note that initial metadata will be affected by the
+  /// \a ServerContext associated with this call.
   void SendInitialMetadata() override {
     GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 
@@ -443,11 +546,13 @@
     call_->cq()->Pluck(&ops);
   }
 
+  /// See the \a ReaderInterface.NextMessageSize method.
   bool NextMessageSize(uint32_t* sz) override {
     *sz = call_->max_receive_message_size();
     return true;
   }
 
+  /// See the \a ReaderInterface.Read method for semantics.
   bool Read(R* msg) override {
     CallOpSet<CallOpRecvMessage<R>> ops;
     ops.RecvMessage(msg);
@@ -465,11 +570,18 @@
 class ServerWriterInterface : public ServerStreamingInterface,
                               public WriterInterface<W> {};
 
+/// Synchronous (blocking) server-side API for doing for doing a
+/// server-streaming RPCs, where the outgoing message stream coming from the
+/// server has messages of type \a W.
 template <class W>
 class ServerWriter final : public ServerWriterInterface<W> {
  public:
   ServerWriter(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
 
+  /// See the \a ServerStreamingInterface.SendInitialMetadata method
+  /// for semantics.
+  /// Note that initial metadata will be affected by the
+  /// \a ServerContext associated with this call.
   void SendInitialMetadata() override {
     GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
 
@@ -484,6 +596,11 @@
     call_->cq()->Pluck(&ops);
   }
 
+  /// See the \a WriterInterface.Write method for semantics.
+  ///
+  /// Side effect:
+  ///   Also sends initial metadata if not already sent (using the
+  ///   \a ClientContext associated with this call to fill in values).
   using WriterInterface<W>::Write;
   bool Write(const W& msg, WriteOptions options) override {
     if (options.is_last_message()) {
@@ -576,20 +693,32 @@
 };
 }  // namespace internal
 
-/// class to represent the user API for a bidirectional streaming call
+/// Synchronous (blocking) server-side API for a bidirectional
+/// streaming call, where the incoming message stream coming from the client has messages of
+/// type \a R, and the outgoing message streaming coming from the server has messages of type \a W.
 template <class W, class R>
 class ServerReaderWriter final : public ServerReaderWriterInterface<W, R> {
  public:
   ServerReaderWriter(Call* call, ServerContext* ctx) : body_(call, ctx) {}
 
+  /// See the \a ServerStreamingInterface.SendInitialMetadata method
+  /// for semantics.
+  /// Note that initial metadata will be affected by the
+  /// \a ServerContext associated with this call.
   void SendInitialMetadata() override { body_.SendInitialMetadata(); }
 
+  /// See the \a ReaderInterface.NextMessageSize method for semantics
   bool NextMessageSize(uint32_t* sz) override {
     return body_.NextMessageSize(sz);
   }
 
+  /// See the \a ReaderInterface.Read method for semantics
   bool Read(R* msg) override { return body_.Read(msg); }
 
+  /// See the \a WriterInterface.Write(const W& msg, WriteOptions options) method for semantics.
+  /// Side effect:
+  ///   Also sends initial metadata if not already sent (using the \a
+  ///   ServerContext associated with this call).
   using WriterInterface<W>::Write;
   bool Write(const W& msg, WriteOptions options) override {
     return body_.Write(msg, options);
@@ -615,12 +744,27 @@
   ServerUnaryStreamer(Call* call, ServerContext* ctx)
       : body_(call, ctx), read_done_(false), write_done_(false) {}
 
+  /// Block to send initial metadata to client.
+  /// Implicit input parameter:
+  ///    - the \a ServerContext associated with this call will be used for
+  ///      sending initial metadata.
   void SendInitialMetadata() override { body_.SendInitialMetadata(); }
 
+  /// Get an upper bound on the request message size from the client.
   bool NextMessageSize(uint32_t* sz) override {
     return body_.NextMessageSize(sz);
   }
 
+  /// Read a message of type \a R into \a msg. Completion will be notified by \a
+  /// tag on the associated completion queue.
+  /// This is thread-safe with respect to \a Write or \a WritesDone methods. It
+  /// should not be called concurrently with other streaming APIs
+  /// on the same stream. It is not meaningful to call it concurrently
+  /// with another \a Read on the same stream since reads on the same stream
+  /// are delivered in order.
+  ///
+  /// \param[out] msg Where to eventually store the read message.
+  /// \param[in] tag The tag identifying the operation.
   bool Read(RequestType* request) override {
     if (read_done_) {
       return false;
@@ -629,6 +773,13 @@
     return body_.Read(request);
   }
 
+  /// Block to write \a msg to the stream with WriteOptions \a options.
+  /// This is thread-safe with respect to \a Read
+  ///
+  /// \param msg The message to be written to the stream.
+  /// \param options The WriteOptions affecting the write operation.
+  ///
+  /// \return \a true on success, \a false when the stream has been closed.
   using WriterInterface<ResponseType>::Write;
   bool Write(const ResponseType& response, WriteOptions options) override {
     if (write_done_ || !read_done_) {
@@ -656,12 +807,27 @@
   ServerSplitStreamer(Call* call, ServerContext* ctx)
       : body_(call, ctx), read_done_(false) {}
 
+  /// Block to send initial metadata to client.
+  /// Implicit input parameter:
+  ///    - the \a ServerContext associated with this call will be used for
+  ///      sending initial metadata.
   void SendInitialMetadata() override { body_.SendInitialMetadata(); }
 
+  /// Get an upper bound on the request message size from the client.
   bool NextMessageSize(uint32_t* sz) override {
     return body_.NextMessageSize(sz);
   }
 
+  /// Read a message of type \a R into \a msg. Completion will be notified by \a
+  /// tag on the associated completion queue.
+  /// This is thread-safe with respect to \a Write or \a WritesDone methods. It
+  /// should not be called concurrently with other streaming APIs
+  /// on the same stream. It is not meaningful to call it concurrently
+  /// with another \a Read on the same stream since reads on the same stream
+  /// are delivered in order.
+  ///
+  /// \param[out] msg Where to eventually store the read message.
+  /// \param[in] tag The tag identifying the operation.
   bool Read(RequestType* request) override {
     if (read_done_) {
       return false;
@@ -670,6 +836,13 @@
     return body_.Read(request);
   }
 
+  /// Block to write \a msg to the stream with WriteOptions \a options.
+  /// This is thread-safe with respect to \a Read
+  ///
+  /// \param msg The message to be written to the stream.
+  /// \param options The WriteOptions affecting the write operation.
+  ///
+  /// \return \a true on success, \a false when the stream has been closed.
   using WriterInterface<ResponseType>::Write;
   bool Write(const ResponseType& response, WriteOptions options) override {
     return read_done_ && body_.Write(response, options);
diff --git a/include/grpc++/impl/server_builder_plugin.h b/include/grpc++/impl/server_builder_plugin.h
index 7697232..8ce16d6 100644
--- a/include/grpc++/impl/server_builder_plugin.h
+++ b/include/grpc++/impl/server_builder_plugin.h
@@ -43,6 +43,10 @@
 class ServerInitializer;
 class ChannelArguments;
 
+/// A builder class for the creation and startup of \a grpc::Server instances.
+/// This is interface is meant for internal usage only. Implementations of this
+/// interface should add themselves to a \a ServerBuilder instance through the
+/// \a InternalAddPluginFactory method.
 class ServerBuilderPlugin {
  public:
   virtual ~ServerBuilderPlugin() {}