diff --git a/data/url/beforeSend-all.html b/data/url/beforeSend-all.html
new file mode 100644
index 00000000..057c9f79
--- /dev/null
+++ b/data/url/beforeSend-all.html
@@ -0,0 +1,69 @@
+<person-list></person-list>
+
+<script type="module">
+import {
+  fixture,
+  restModel,
+  ObservableObject,
+  StacheElement,
+} from "can/ecosystem";
+
+setupFixtures();
+
+class Person extends ObservableObject {
+  static props = {
+    firstName: String,
+    lastName: String,
+    age: Number,
+  };
+}
+
+const personConnection = restModel({
+  Map: Person,
+  url: {
+    resource: '/api/person',
+    beforeSend(xhr) {
+      xhr.setRequestHeader('Authorization', 'Bearer: some-authorization-token');
+    }
+  }
+});
+
+class PersonList extends StacheElement {
+  static view =`
+    <button on:click="this.getList()">Make request for person list</button>
+    <ul>
+      {{#for(person of this.people)}}
+        <li>{{person.firstName}} {{person.lastName}} - {{person.age}}</li>
+      {{else}}
+        <li>No people loaded.</li>
+      {{/for}}
+    </ul>
+  `;
+
+  static props = {
+    people: {
+      get default() { return []; }
+    }
+  };
+
+  getList() {
+    personConnection.getList().then((list) => {;
+      this.people = list;
+    });
+  }
+}
+customElements.define("person-list", PersonList);
+
+function setupFixtures() {
+  fixture("GET /api/person", function (request, response) {
+    if (request.headers.Authorization) { // validate auth header
+      response([
+        {firstName: 'Keanu', lastName: 'Reeves', age: 55},
+        {firstName: 'Tom', lastName: 'Cruise', age: 57},
+      ]);
+    } else {
+      response(401, {message: "Unauthorized"}, {}, "unauthorized");
+    }
+  });
+}
+</script>
diff --git a/data/url/custom-request.html b/data/url/custom-request.html
new file mode 100644
index 00000000..a05c52f1
--- /dev/null
+++ b/data/url/custom-request.html
@@ -0,0 +1,89 @@
+<todo-list></todo-list>
+
+<script type="module">
+  import {
+    ajax,
+    fixture,
+    restModel,
+    ObservableObject,
+    StacheElement,
+  } from "can/ecosystem";
+
+  setupFixtures();
+
+  class Todo extends ObservableObject {
+    static props = {
+      id: Number,
+      content: String,
+      complete: Boolean,
+    };
+  }
+
+  const todoConnection = restModel({
+    Map: Todo,
+    url: {
+      resource: "/services/todo",
+      getListData: "GET /services/todos",
+      getData: function(param){
+        return ajax({
+          url: '/services/todo',
+          data: { identifier: param.id }
+        });
+      }
+    }
+  });
+
+  class TodoList extends StacheElement {
+    static view =`
+      <button on:click="this.getList()">Make request for Todo list</button>
+      <ul>
+        {{#for(todo of this.todos)}}
+          <li on:click="this.getTodo(todo.id)">{{todo.id}}</li>
+        {{else}}
+          <li>No todos loaded.</li>
+        {{/for}}
+      </ul>
+
+      {{#if this.activeTodo}}
+        <h3>Active Todo:</h3>
+        <p>{{this.activeTodo.content}} - <input type="checkbox" disabled checked:from="{{this.activeTodo.complete}}"></p>
+      {{/if}}
+    `;
+
+    static props = {
+      todos: {
+        get default() { return []; }
+      },
+      activeTodo: Todo
+    };
+
+    getList() {
+      todoConnection.getList().then((list) => {
+        this.todos = list;
+      });
+    }
+
+    getTodo(id) {
+      todoConnection.get({id}).then((todo) => {
+        this.activeTodo = todo;
+      })
+    }
+  }
+  customElements.define("todo-list", TodoList);
+
+  function setupFixtures() {
+    const todos = [
+      {id: 1, content: 'Do the dishes', complete: true},
+      {id: 2, content: 'Walk the dog', complete: false},
+      {id: 3, content: 'Sweep the floor', complete: false},
+    ];
+
+    fixture("GET /services/todos", function (request, response) {
+      response(todos);
+    });
+
+    fixture("GET /services/todo", function (request, response) {
+      response(todos[request.data.identifier - 1]);
+    })
+  }
+</script>
diff --git a/data/url/plain-endpoints.html b/data/url/plain-endpoints.html
new file mode 100644
index 00000000..e96bf0c5
--- /dev/null
+++ b/data/url/plain-endpoints.html
@@ -0,0 +1,96 @@
+<request-demo></request-demo>
+
+<script type="module">
+import {
+  fixture,
+  restModel,
+  ObservableObject,
+  StacheElement,
+} from "can/ecosystem";
+
+setupFixtures();
+
+class Todo extends ObservableObject {
+  static props = {
+    id: Number,
+    content: String,
+    complete: Boolean,
+  };
+}
+
+const todoConnection = restModel({
+  Map: Todo,
+  url: {
+    getListData: "GET /services/todos",
+    getData: "GET /services/todo/{id}",
+    createData: "POST /services/todo",
+    updateData: "PUT /services/todo/{id}",
+    destroyData: "DELETE /services/todo/{id}"
+  }
+});
+
+class RequestDemo extends StacheElement {
+  static view =`
+    <button on:click="this.getList()">Todo list request</button>
+    <button on:click="this.get()">Single todo request</button>
+    <button on:click="this.create()">Todo creation request</button>
+    <button on:click="this.update()">Todo update request</button>
+    <button on:click="this.delete()">Todo deletion request</button>
+  `;
+
+  getList() {
+    todoConnection.getList();
+  }
+
+  get() {
+    todoConnection.get({id: 5});
+  }
+
+  create() {
+    new Todo({
+      content: 'New todo',
+      complete: false,
+    }).save();
+  }
+
+  update() {
+    new Todo({
+      id: 1,
+      content: 'Old todo',
+      complete: true,
+    }).save(); // makes an update request since this instance already has an id
+  }
+
+  delete() {
+    new Todo({
+      id: 1,
+      content: 'Old todo',
+      complete: true,
+    }).destroy();
+  }
+}
+customElements.define("request-demo", RequestDemo);
+
+function setupFixtures() {
+  fixture("GET /services/todos", function (request, response) {
+    console.log('Todo list request');
+    response([]);
+  });
+  fixture("GET /services/todo/{id}", function (request, response) {
+    console.log(`Todo id ${request.data.id} request`);
+    response({});
+  });
+  fixture("POST /services/todo", function (request, response) {
+    console.log(`Todo created`);
+    response({});
+  });
+  fixture("PUT /services/todo/{id}", function (request, response) {
+    console.log(`Todo id ${request.data.id} updated`);
+    response({});
+  });
+  fixture("DELETE /services/todo/{id}", function (request, response) {
+    console.log(`Todo id ${request.data.id} deleted`);
+    response({});
+  });
+}
+</script>
diff --git a/data/url/request-params.html b/data/url/request-params.html
new file mode 100644
index 00000000..1a363880
--- /dev/null
+++ b/data/url/request-params.html
@@ -0,0 +1,85 @@
+<todo-list></todo-list>
+
+<script type="module">
+  import {
+    ajax,
+    fixture,
+    restModel,
+    ObservableObject,
+    StacheElement,
+  } from "can/ecosystem";
+
+  setupFixtures();
+
+  class Todo extends ObservableObject {
+    static props = {
+      id: Number,
+      content: String,
+      complete: Boolean,
+    };
+  }
+
+  function processContext() {
+    // react to the response of the '/services/context' request before sending getListData request
+  }
+
+  const todoConnection = restModel({
+    Map: Todo,
+    url: {
+      resource: "/services/todos",
+      getListData: {
+        url: "/services/todos",
+        type: "GET",
+        beforeSend: () => {
+          return ajax({url: '/services/context'}).then(processContext);
+        }
+      }
+    }
+  });
+
+  class TodoList extends StacheElement {
+    static view =`
+      <button on:click="this.getList()">Make request for Todo list</button>
+      <ul>
+        {{#for(todo of this.todos)}}
+          <li>
+            <input type="checkbox" disabled checked:from="{{todo.complete}}">
+            {{todo.id}} - {{todo.content}}
+          </li>
+        {{else}}
+          <li>No todos loaded.</li>
+        {{/for}}
+      </ul>
+    `;
+
+    static props = {
+      todos: {
+        get default() { return []; }
+      },
+    };
+
+    getList() {
+      todoConnection.getList().then((list) => {
+        this.todos = list;
+      });
+    }
+  }
+  customElements.define("todo-list", TodoList);
+
+  function setupFixtures() {
+    const todos = [
+      {id: 1, content: 'Do the dishes', complete: true},
+      {id: 2, content: 'Walk the dog', complete: false},
+      {id: 3, content: 'Sweep the floor', complete: false},
+    ];
+
+    fixture("GET /services/todos", function (request, response) {
+      response(todos);
+    });
+
+    // arbitrary preliminary request
+    fixture("GET /services/context", function (request, response) {
+      response({});
+    });
+  }
+</script>
diff --git a/data/url/resource-param.html b/data/url/resource-param.html
new file mode 100644
index 00000000..9fbe75e9
--- /dev/null
+++ b/data/url/resource-param.html
@@ -0,0 +1,83 @@
+<todo-list></todo-list>
+
+<script type="module">
+  import {
+    ajax,
+    fixture,
+    restModel,
+    ObservableObject,
+    StacheElement,
+  } from "can/ecosystem";
+
+  setupFixtures();
+
+  class Todo extends ObservableObject {
+    static props = {
+      id: Number,
+      content: String,
+      complete: Boolean,
+    };
+  }
+
+  const todoConnection = restModel({
+    Map: Todo,
+    url: {
+      resource: "/services/todo",
+      getListData: "GET /services/todos",
+    }
+  });
+
+  class TodoList extends StacheElement {
+    static view =`
+      <button on:click="this.getList()">Make request for Todo list</button>
+      <ul>
+        {{#for(todo of this.todos)}}
+          <li on:click="this.getTodo(todo.id)">{{todo.id}}</li>
+        {{else}}
+          <li>No todos loaded.</li>
+        {{/for}}
+      </ul>
+
+      {{#if this.activeTodo}}
+        <h3>Active Todo:</h3>
+        <p>{{this.activeTodo.content}} - <input type="checkbox" disabled checked:from="{{this.activeTodo.complete}}"></p>
+      {{/if}}
+    `;
+
+    static props = {
+      todos: {
+        get default() { return []; }
+      },
+      activeTodo: Todo
+    };
+
+    getList() {
+      todoConnection.getList().then((list) => {
+        this.todos = list;
+      });
+    }
+
+    getTodo(id) {
+      todoConnection.get({id}).then((todo) => {
+        this.activeTodo = todo;
+      })
+    }
+  }
+  customElements.define("todo-list", TodoList);
+
+  function setupFixtures() {
+    const todos = [
+      {id: 1, content: 'Do the dishes', complete: true},
+      {id: 2, content: 'Walk the dog', complete: false},
+      {id: 3, content: 'Sweep the floor', complete: false},
+    ];
+
+    fixture("GET /services/todos", function (request, response) {
+      response(todos);
+    });
+
+    fixture("GET /services/todo/{id}", function (request, response) {
+      response(todos[parseInt(request.data.id) - 1]);
+    })
+  }
+</script>
diff --git a/data/url/url.js b/data/url/url.js
index 5a81a2ec..10fa2bd1 100644
--- a/data/url/url.js
+++ b/data/url/url.js
@@ -159,93 +159,6 @@ var urlBehavior = behavior("data/url", function(baseConnection) {
 
 	return behavior;
 });
-/**
- * @property {String|Object} can-connect/data/url/url.url url
- * @parent can-connect/data/url/url.option
- *
- * Specify the url and methods that should be used for the "Data Methods".
- *
- * @option {String} If a string is provided, it's assumed to be a RESTful interface. For example,
- * if the following is provided:
- *
- * ```
- * url: "/services/todos"
- * ```
- *
- * ... the following methods and requests are used:
- *
- *  - `getListData` - `GET /services/todos`
- *  - `getData` - `GET /services/todos/{id}`
- *  - `createData` - `POST /services/todos`
- *  - `updateData` - `PUT /services/todos/{id}`
- *  - `destroyData` - `DELETE /services/todos/{id}`
- *
- * @option {Object} If an object is provided, it can customize each method and URL directly
- * like:
- *
- * ```js
- * url: {
- *   getListData: "GET /services/todos",
- *   getData: "GET /services/todo/{id}",
- *   createData: "POST /services/todo",
- *   updateData: "PUT /services/todo/{id}",
- *   destroyData: "DELETE /services/todo/{id}"
- * }
- * ```
- *
- * You can provide a `resource` property that works like providing `url` as a string, but overwrite
- * other values like:
- *
- * ```js
- * url: {
- *   resource: "/services/todo",
- *   getListData: "GET /services/todos"
- * }
- * ```
- *
- * You can also customize per-method the parameters passed to the [can-connect/data/url/url.ajax ajax implementation], like:
- * ```js
- * url: {
- *   resource: "/services/todos",
- *   getListData: {
- *     url: "/services/todos",
- *     type: "GET",
- *     beforeSend: () => {
- *       return fetch('/services/context').then(processContext);
- *     }
- *   }
- * }
- * ```
- * This can be particularly useful for passing a handler for the [can-ajax <code>beforeSend</code>] hook.
- *
- * The [can-ajax <code>beforeSend</code>] hook can also be passed for all request methods. This can be useful when
- * attaching a session token header to a request:
- * 
- * ```js
- * url: {
- *   resource: "/services/todos",
- *   beforeSend: (xhr) => {
- *     xhr.setRequestHeader('Authorization', `Bearer: ${Session.current.token}`);
- *   }
- * }
- * ```
- *
- * Finally, you can provide your own method to totally control how the request is made:
- *
- * ```js
- * url: {
- *   resource: "/services/todo",
- *   getListData: "GET /services/todos",
- *   getData: function(param){
- *     return new Promise(function(resolve, reject){
- *       $.get("/services/todo", {identifier: param.id}).then(resolve, reject);
- *     });
- *   }
- * }
- * ```
- */
-
-
  /**
   * @property {function} can-connect/data/url/url.ajax ajax
   * @parent can-connect/data/url/url.option
diff --git a/data/url/url.url.md b/data/url/url.url.md
new file mode 100644
index 00000000..1c5b4009
--- /dev/null
+++ b/data/url/url.url.md
@@ -0,0 +1,53 @@
+@property {String|Object} can-connect/data/url/url.url url
+@parent can-connect/data/url/url.option
+
+Specify the url and methods that should be used for the "Data Methods".
+
+@option {String} If a string is provided, it's assumed to be a RESTful interface. For example,
+if the following is provided:
+
+```
+url: "/services/todos"
+```
+
+... the following methods and requests are used:
+
+ - `getListData` - `GET /services/todos`
+ - `getData` - `GET /services/todos/{id}`
+ - `createData` - `POST /services/todos`
+ - `updateData` - `PUT /services/todos/{id}`
+ - `destroyData` - `DELETE /services/todos/{id}`
+
+@option {Object} If an object is provided, it can customize each method and URL directly
+like:
+
+ @sourceref ./plain-endpoints.html
+ @highlight 23-29,only
+ @codepen
+
+You can provide a `resource` property that works like providing `url` as a string, but overwrite
+other values like:
+
+ @sourceref ./resource-param.html
+ @highlight 25,only
+ @codepen
+
+You can also customize per-method the parameters passed to the [can-connect/data/url/url.ajax ajax implementation], like:
+ @sourceref ./request-params.html
+ @highlight 30-36,only
+ @codepen
+This can be particularly useful for passing a handler for the [can-ajax <code>beforeSend</code>] hook.
+
+<a id="beforeSend"></a>
+The [can-ajax <code>beforeSend</code>] hook can also be passed for all request methods. This can be useful when
+attaching a session token header to a request:
+
+ @sourceref ./beforeSend-all.html
+ @highlight 25-27,only
+ @codepen
+
+Finally, you can provide your own method to totally control how the request is made:
+
+ @sourceref ./custom-request.html
+ @highlight 27-32,only
+ @codepen
\ No newline at end of file