diff --git a/examples/README.md b/examples/README.md
index dcb5229c784e2052e92016ef7d081c139a626d63..42df4ce568aa8e6c924dc32badc8f5a99efdd55d 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -1,6 +1,137 @@
-# Example
+# Examples
 
-# Bootstrap Client & Server
+## Basic client usage
+
+The basic-client example shows the use of the most of the functioanlity of the
+`ca.Client`, those methods works as an SDK for integrating other services with
+the Certificate Authority (CA).
+
+In [basic-client/client.go](/examples/basic-client/client.go) we first can see
+the initialization of the client:
+
+```go
+client, err := ca.NewClient("https://localhost:9000", ca.WithRootSHA256("84a033e84196f73bd593fad7a63e509e57fd982f02084359c4e8c5c864efc27d"))
+```
+
+The previous code uses the CA address and the root certificate fingerprint.
+The CA url will be present in the token, and the root fingerprint can be present
+too if the `--root root_ca.crt` option is use in the creation of the token. If
+this is the case is simpler to rely in the token and use just:
+
+```go
+client, err := ca.Bootstrap(token)
+```
+
+After the initialization there're examples of all the client methods, they are
+just a convenient way to use the CA API endpoints. The first method `Health`
+returns the status of the CA server, on the first implementation if the server
+is up it will return just ok.
+
+```go
+health, err := client.Health()
+// Health is a struct created from the JSON response {"status": "ok"}
+```
+
+The next method `Root` is used to get and verify the root certificate. We will
+pass a finger print, it will download the root certificate from the CA and it
+will make sure that the fingerprint matches. This method uses an insecure HTTP
+client as it might be used in the initialization of the client, but the response
+is considered secure because we have compared against the given digest.
+
+```go
+root, err := client.Root("84a033e84196f73bd593fad7a63e509e57fd982f02084359c4e8c5c864efc27d")
+```
+
+After Root we have the most important method `Sign`, this is used to sign a
+Certificate Signing Request that we provide. To secure this request we use
+the one-time-token. You can build your own certificate request and add it in
+the `*api.SignRequest`, but the ca package contains a method that will create a
+secure random key, and create the CSR based on the information in the token.
+
+```go
+// Create a CSR from token and return the sign request, the private key and an
+// error if something failed.
+req, pk, err := ca.CreateSignRequest(token)
+if err != nil { ... }
+
+// Do the sign request and return the signed certificate
+sign, err := client.Sign(req)
+if err != nil { ... }
+```
+
+To renew the certificate we can use the `Renew` method, the certificate renewal
+relies on a mTLS connection with a previous certificate, so we will need to pass
+a transport with the previous certificate.
+
+```go
+// Get a cancelable context to stop the renewal goroutines and timers.
+ctx, cancel := context.WithCancel(context.Background())
+defer cancel()
+// Create a transport from with the sign response and the private key.
+tr, err := client.Transport(ctx, sign, pk)
+if err != nil { ... }
+// Renew the certificate and get the new ones.
+// The return type are equivalent to ones in the Sign method.
+renew, err := client.Renew(tr)
+if err != nil { ... }
+```
+
+All the previous methods map with one endpoint in the CA API, but the API
+provides a couple more that are used for creating the tokens. For those we have
+a couple of methods, one that returns a list of provisioners and one that
+returns the encrypted key of one provisioner.
+
+```go
+// Without options it will return the first 20 provisioners
+provisioners, err := client.Provisioners()
+// We can also set a limit up to 100
+provisioners, err := client.Provisioners(ca.WithProvisionerLimit(100))
+// With a pagination cursor
+provisioners, err := client.Provisioners(ca.WithProvisionerCursor("1f18c1ecffe54770e9107ce7b39b39735"))
+// Or combining both
+provisioners, err := client.Provisioners(
+    ca.WithProvisionerCursor("1f18c1ecffe54770e9107ce7b39b39735"),
+    ca.WithProvisionerLimit(100),
+)
+
+// Return the encrypted key of one of the returned provisioners. The key
+// returned is an encrypted JWE with the private key used to sign tokens.
+key, err := client.ProvisionerKey("DmAtZt2EhmZr_iTJJ387fr4Md2NbzMXGdXQNW1UWPXk")
+```
+
+The example shows also the use of some helper methods used to get configured
+tls.Config objects that can be injected in servers and clients. These methods,
+are also configured to auto-renew the certificate once two thirds of the
+duration of the certificate has passed, approximately.
+
+```go
+// Get a cancelable context to stop the renewal goroutines and timers.
+ctx, cancel := context.WithCancel(context.Background())
+defer cancel()
+// Get tls.Config for a server
+tlsConfig, err := client.GetClientTLSConfig(ctx, sign, pk)
+// Get tls.Config for a client
+tlsConfig, err := client.GetClientTLSConfig(ctx, sign, pk)
+// Get an http.Transport for a client, this can be used as a http.RoundTripper
+// in an http.Client
+tr, err := client.Transport(ctx, sign, pk)
+```
+
+To run the example you need to start the certificate authority:
+
+```
+certificates $ bin/step-ca examples/pki/config/ca.json
+2018/11/02 18:29:25 Serving HTTPS on :9000 ...
+```
+
+And just run the client.go with a new token:
+```
+certificates $ export STEPPATH=examples/pki
+certificates $ export STEP_CA_URL=https://localhost:9000
+certificates $ go run examples/basic-client/client.go $(step ca new-token client.smallstep.com))
+```
+
+## Bootstrap Client & Server
 
 On this example we are going to see the Certificate Authority running, as well
 as a simple Server using TLS and a simple client doing TLS requests to the
@@ -18,7 +149,7 @@ certificates $ bin/step-ca examples/pki/config/ca.json
 We will start the server and we will type `password` when step asks for the
 provisioner password:
 ```
-certificates $ export STEPPATH=examples/pki 
+certificates $ export STEPPATH=examples/pki
 certificates $ export STEP_CA_URL=https://localhost:9000
 certificates $ go run examples/bootstrap-server/server.go $(step ca new-token localhost))
 ✔ Key ID: DmAtZt2EhmZr_iTJJ387fr4Md2NbzMXGdXQNW1UWPXk (mariano@smallstep.com)
@@ -56,7 +187,7 @@ detected a TLS client configuration.
 
 But if we the client with the certificate name Mike we'll see:
 ```
-certificates $ export STEPPATH=examples/pki 
+certificates $ export STEPPATH=examples/pki
 certificates $ export STEP_CA_URL=https://localhost:9000
 certificates $ go run examples/bootstrap-client/client.go $(step ca new-token Mike)
 ✔ Key ID: DmAtZt2EhmZr_iTJJ387fr4Md2NbzMXGdXQNW1UWPXk (mariano@smallstep.com)
diff --git a/examples/basic-client/client.go b/examples/basic-client/client.go
new file mode 100644
index 0000000000000000000000000000000000000000..4ea4d7930a6f0062d097966bac64b1fae471c291
--- /dev/null
+++ b/examples/basic-client/client.go
@@ -0,0 +1,152 @@
+package main
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"net"
+	"net/http"
+	"os"
+	"time"
+
+	"github.com/smallstep/certificates/ca"
+)
+
+func printResponse(name string, v interface{}) {
+	b, err := json.MarshalIndent(v, "", "  ")
+	if err != nil {
+		panic(err)
+	}
+	fmt.Printf("%s response:\n%s\n\n", name, b)
+}
+
+func main() {
+	if len(os.Args) != 2 {
+		fmt.Fprintf(os.Stderr, "Usage: %s <token>\n", os.Args[0])
+		os.Exit(1)
+	}
+
+	token := os.Args[1]
+
+	// To create the client using ca.NewClient we need:
+	// * The CA address "https://localhost:9000"
+	// * The root certificate fingerprint
+	// 84a033e84196f73bd593fad7a63e509e57fd982f02084359c4e8c5c864efc27d to get
+	// the root fingerprint we can use `step certificate fingerprint root_ca.crt`
+	client, err := ca.NewClient("https://localhost:9000", ca.WithRootSHA256("84a033e84196f73bd593fad7a63e509e57fd982f02084359c4e8c5c864efc27d"))
+	if err != nil {
+		panic(err)
+	}
+
+	// Other ways to initialize the client would be:
+	// * With the Bootstrap functionality (recommended):
+	//   client, err := ca.Bootstrap(token)
+	// * Using the root certificate instead of the fingerprint:
+	//   client, err := ca.NewClient("https://localhost:9000", ca.WithRootFile("../pki/secrets/root_ca.crt"))
+
+	// Get the health of the CA
+	health, err := client.Health()
+	if err != nil {
+		panic(err)
+	}
+	printResponse("Health", health)
+
+	// Get and verify a root CA
+	root, err := client.Root("84a033e84196f73bd593fad7a63e509e57fd982f02084359c4e8c5c864efc27d")
+	if err != nil {
+		panic(err)
+	}
+	printResponse("Root", root)
+
+	// We can use ca.CreateSignRequest to generate a new sign request with a
+	// randomly generated key.
+	req, pk, err := ca.CreateSignRequest(token)
+	if err != nil {
+		panic(err)
+	}
+	sign, err := client.Sign(req)
+	if err != nil {
+		panic(err)
+	}
+	printResponse("Sign", sign)
+
+	// Renew a certificate with a transport that contains the previous
+	// certificate. We should created a context that allows us to finish the
+	// renewal goroutine.∑
+	ctx, cancel := context.WithCancel(context.Background())
+	defer cancel() // Finish the renewal goroutine
+	tr, err := client.Transport(ctx, sign, pk)
+	if err != nil {
+		panic(err)
+	}
+	renew, err := client.Renew(tr)
+	if err != nil {
+		panic(err)
+	}
+	printResponse("Renew", renew)
+
+	// Get tls.Config for a server
+	ctxServer, cancelServer := context.WithCancel(context.Background())
+	defer cancelServer()
+	tlsConfig, err := client.GetServerTLSConfig(ctxServer, sign, pk)
+	if err != nil {
+		panic(err)
+	}
+	// An http server will use the tls.Config like:
+	_ = &http.Server{
+		Addr: ":443",
+		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+			w.Write([]byte("Hello world"))
+		}),
+		TLSConfig: tlsConfig,
+	}
+
+	// Get tls.Config for a client
+	ctxClient, cancelClient := context.WithCancel(context.Background())
+	defer cancelClient()
+	tlsConfig, err = client.GetClientTLSConfig(ctxClient, sign, pk)
+	// An http.Client will need to create a transport first
+	_ = &http.Client{
+		Transport: &http.Transport{
+			TLSClientConfig: tlsConfig,
+			// Options set in http.DefaultTransport
+			Proxy: http.ProxyFromEnvironment,
+			DialContext: (&net.Dialer{
+				Timeout:   30 * time.Second,
+				KeepAlive: 30 * time.Second,
+				DualStack: true,
+			}).DialContext,
+			MaxIdleConns:          100,
+			IdleConnTimeout:       90 * time.Second,
+			TLSHandshakeTimeout:   10 * time.Second,
+			ExpectContinueTimeout: 1 * time.Second,
+		},
+	}
+
+	// But we can just use client.Transport to get the default configuration
+	ctxTransport, cancelTransport := context.WithCancel(context.Background())
+	defer cancelTransport()
+	tr, err = client.Transport(ctxTransport, sign, pk)
+	// And http.Client will use the transport like
+	_ = &http.Client{
+		Transport: tr,
+	}
+
+	// Get provisioners and provisioner keys. In this example we add two
+	// optional arguments with the initial cursor and a limit.
+	//
+	// A server or a client should not need this functionality, they are used to
+	// sign (private key) and verify (public key) tokens. The step cli can be
+	// used for this purpose.
+	provisioners, err := client.Provisioners(ca.WithProvisionerCursor(""), ca.WithProvisionerLimit(100))
+	if err != nil {
+		panic(err)
+	}
+	printResponse("Provisioners", provisioners)
+	// Get encrypted key
+	key, err := client.ProvisionerKey("DmAtZt2EhmZr_iTJJ387fr4Md2NbzMXGdXQNW1UWPXk")
+	if err != nil {
+		panic(err)
+	}
+	printResponse("Provisioner Key", key)
+}