diff --git a/lib/RedMiner/API.pm b/lib/RedMiner/API.pm
index c23e6574560aed8584ad7c2a7ff86474368471b6..111846ffa830b57ab60e73a259b97783e5f296ea 100644
--- a/lib/RedMiner/API.pm
+++ b/lib/RedMiner/API.pm
@@ -6,6 +6,9 @@ use warnings;
 
 our $VERSION = '0.03';
 
+# 2DO: http://www.redmine.org/projects/redmine/wiki/Rest_api#User-Impersonation
+# 2DO: implement (un)?wrapping
+
 use URI;
 use URI::QueryParam;
 use LWP::UserAgent;
@@ -23,16 +26,145 @@ RedMiner::API - Wrapper for RedMine REST API (http://www.redmine.org/projects/re
 =head1 SYNOPSIS
 
 	use RedMiner::API;
+	my $redminer = RedMiner::API->new(
+		host => 'example.com/redmine',
+		key  => 'xxx',
+	);
+	# password-based auth is also supported:
+	#my $redminer = RedMiner::API->new(
+	#	host => 'example.com/redmine',
+	#	user => 'redminer',
+	#	pass => 'p@s$w0rD',
+	#);
+
+	my $project = $redminer->createProject({
+		identifier  => 'my-project',
+		name        => 'My Project',
+		description => 'My project, created with *RedMiner::API*',
+	});
+	if (!$project) {
+		say STDERR 'Error(s) creating project: ', join("\n", map { $_ } $redminer->errorDetails->{errors});
+		exit 1;
+	}
+	my $project_id = $project->{project}{id};
+
+	$redminer->updateProject($project_id, {
+		parent_id       => 42, # Make a project with numeric ID 42  parent for $project_id
+		inherit_members => 1,  # Inherit all members and their permissions from the parent
+	});
+	
+	my $issue = $redminer->createIssue({
+		project_id  => $project_id,
+		subject     => 'Test issue for RedMiner::API',
+		description => 'Issue description',
+	});
+
+	$redminer->deleteProject($project_id);
 
 =head1 DESCRIPTION
 
-Stub documentation for RedMiner::API, created by h2xs. It looks like the
-author of the extension was negligent enough to leave the stub
-unedited.
+This module provides a thin client for RedMine REST API. Please note that although
+RedMine API is designed to support both JSON and XML, this module is B<JSON only>.
+
+=head1 METHODS NAMING AND OTHER CALL CONVENTIONS
+
+All methods are dynamically converted to actual HTTP requests using following conventions.
+
+=head2 Getting a Collection of Objects
+
+	$redminer->projects;     # ->users,     ->issues,     ->timeEntries     ...
+	$redminer->getProjects;  # ->getUsers,  ->getIssues,  ->getTimeEntries  ...
+	$redminer->readProjects; # ->readUsers, ->readIssues, ->readTimeEntries ...
+	
+	# Second page when displaying 10 items per page:
+	$redminer->projects({ offset => 9, limit => 10 });
+
+	# Filtering issues:
+	$redminer->issues({ project_id => 42, assigned_to_id => 'me' });
+
+=head2 Getting an Object
+
+	$redminer->project(1);     # ->user(1),      ->issue(1),     ->timeEntry(1)     ...
+	$redminer->getProject(1);  # ->getUser(1),   ->getIssue(1),  ->getTimeEntry(1)  ...
+	$redminer->readProject(1); # ->readUsers(1), ->readIssue(1), ->readTimeEntry(1) ...
+	
+	# Showing anobject with additional metadata:
+	$redminer->issue(1, { include => 'relations,changesets' });
+
+=head2 Creating an Object
+
+	$redminer->createProject({
+		# ...
+	}); # ->createUser, ->createIssue, ->createTimeEntry ...
+
+=head2 Updating an Object
+
+	$redminer->updateProject(1, {
+		# ...
+	}); # ->updateUser(...), ->updateIssue(...), ->updateTimeEntry(...) ...
+
+=head2 Deleting an Object
+
+	$redminer->deleteProject(1); # ->deleteUser(1), ->deleteIssue(1), ->deleteTimeEntry(1) ...
+
+=head2 Objects Belonging to Other Objects
+
+	# Example for project membership(s)
+	my $project_id    = 42;
+	my $membership_id = 42;
+
+	# Listing *project* memberships and creating a membership within a *project*
+	# require identifying a project and thus have to be spelled like this:
+	$redminer->projectMemberships($project_id, { limit => 50 });
+	$redminer->createProjectMembership($project_id, { ... });
+
+	# Viewing/Updating/Deleting a membership is performed directly by its ID, thus:
+	my $membership = $redminer->membership($membership_id);
+	$redminer->updateMembership($membership_id, { ... });
+	$redminer->deleteMembership($membership_id);
+
+=head2 Complex Object Names
+
+Such complex names as C<TimeEntry> which should be dispatched to C<time_entries>
+are recognized and thus can be spelled in a natural language way (see examples above).
+If this is not the case, please report bugs.
+
+=head2 Return Values
+
+All successfull calls return hash references. For C<update*> and C<delete*> calls
+hash references are empty.
 
-=head2 EXPORT
+If a call fails, C<undef> is returned. In this case detailed error information can
+be retrieved like this:
+	
+	if (!$redminer->deleteIssue(42)) {
+		my $details = $redminer->errorDetails;
+		# Process $details here...
+	}
+
+=head1 METHODS
+
+=head2 new
+
+	my $redminer = RedMiner::API->new(%options);
+
+Following options are recognized:
+
+=over
+
+=item *
 
-None.
+B<host>: RedMine host. Beside host name, may include port, path and/or URL scheme (C<http> is used by default).
+
+=item *
+
+B<key>: API key. For additional information, please refer to http://www.redmine.org/projects/redmine/wiki/Rest_api#Authentication
+
+=item *
+
+B<user>, B<pass>: User name and password for password-based authentication
+
+=back
 
 =cut
 
@@ -77,8 +209,34 @@ sub new
 	bless $self, $class;
 }
 
+=head2 error
+
+Error during the last call. This is an empty string for successfull calls, otherwise
+it contains an HTTP status line.
+
+If the call failed before sending an actual request (e.g. method name could not
+be dispatched into an HTTP request), contains description of the client error.
+
+=cut
+
 sub error        { $_[0]->{error} }
+
+=head2 errorDetails
+
+Contains detailed error messages from the last call. This is an empty hash reference
+for successfull calls, otherwise please see http://www.redmine.org/projects/redmine/wiki/Rest_api#Validation-errors.
+
+If the call failed before sending an actual request (e.g. method name could not
+be dispatched into an HTTP request), return value is
+
+	{
+		client_error => 1
+	}
+
+=cut
+
 sub errorDetails { $_[0]->{error_details} }
+
 sub _set_error   { $_[0]->{error} = $_[1] // ''; return; }
 
 sub _set_client_error
@@ -144,6 +302,8 @@ sub _response
 		return $self->_set_error($response->status_line);
 	}
 
+	$self->{error_details} = {};
+
 	if ($request->method eq 'PUT' || $request->method eq 'DELETE') {
 		return {};
 	}