diff --git a/docs/ape.md b/docs/ape.md
new file mode 100644
index 0000000..a239499
--- /dev/null
+++ b/docs/ape.md
@@ -0,0 +1,85 @@
+# Access policy engine
+
+## General overview
+
+### Purpose
+
+Access policy engine (APE) is aimed at checking if a request can be performed over a resource by looking up the set chains of rules.
+
+#### Terms
+
+| Term | Description | Structure overview |
+| -------------- | -------------------------------------------------------------- | -------------- |
+| `Request` | The action that is being performed on the `Resource`. |
`Operation` - `GetObject`,`PutObject` etc.;
`Properties` - actor's public key, actor's attributes;
`Resource`.
|
+| `Resource` | The object that the request is being performed on. Check also [resource.md](./resource.md). |
`Name` - strictly formatted string value;
`Properties`.
|
+| `Chain` | A chain of `Rule`-s defined for a specific target. Chains are strictly distinguished by `Name`-s , i.e. chains with name `ingress` are not intersected with chains with name `s3`. Chains are stored in serialized format. |
Base64-encoded `ID`;
List of `Rule`-s;
`MatchType` - defines rule status selection priority.
|
+| `Rule` | `Rule` defines which status is returned if `Request` matches all conditions. |
`Actions` - operation defined by a schema (`GetObject`, `PutContainer` etc.);
`Resources`;
`Any` - if `true` then `Reqeust` matches `Rule` if any `Condition` is `true`;
`Conditions`.
|
+| `Name` | `Name` of a chain (do not confuse with chain ID). `Name` defines a layer of `Chain`'s usage, so chains are distinguished by `Name`-s. Basically, `Name` refers to a protocol. | String value (`ingress`, `s3`, `iam`). |
+| `Target` | A scope of request. `Target` can be either simple (only namespace; only container; only user; only groups) or compound (namespace + container). |
`Namespace`;
`Container`;
`User`;
`Groups`.
|
+| `Engine` | `Engine` checks a request in a scope defined by `Target`. First, it is trying to match a request with rules defined in `LocalOverrideStorage` and, then, in `MorphRuleChainStorage`. |
`LocalOverrideStorage` - chains stored in the local override storage have the highest priority
`MorphRuleChainStorage` - basically, chains stored in `Policy` contract;
`ChainRouter` - looks up chains and try to match them with `Request`.
|
+
+#### Details
+
+Here some entities are overviewed in more detail.
+
+##### Resource
+
+`Resource`'s name is strictly formatted, the format is defined by a schema (`native`, `aws` etc.). Examples:
+
+```bash
+# The resource is the particular object with the address within Root namespace
+native:object//HRwWbb1bJjRms33kkA21hy4JdPfARaH3fW9NfuNN6Fgj/EbxzAdz5LB4uqxuz6crWKAumBNtZyK2rKsqQP7TdZvwr
+# The resource is all objects within the container within Root namespace
+native:object//HRwWbb1bJjRms33kkA21hy4JdPfARaH3fW9NfuNN6Fgj/*
+# The resource is the particular container within the namespace
+native:container/namespace1/HRwWbb1bJjRms33kkA21hy4JdPfARaH3fW9NfuNN6Fgj
+# The resource is all containers within the namespace
+native:container/namespace1/*
+```
+
+##### Rule
+
+`Rule` works out if:
+
+ 1. a requests's operation matches the rule's `Actions`;
+ 2. resource name matches the rule's `Resources`;
+ 3. if all (or at least one if `Any=true`) conditions in `Condition` is met. Each condition defines how to retrieve
+and compare the retrieved value. If `Condition`'s `Object` is set to `Resource` then the value is retrieved from the
+resource's properties (example: container zone attribute). If `Object` is set to `Request`, the it's retrieved from the request's properties (example: actor's public key).
+
+###### Name matching
+
+`Resource`'s name in `Rule` may contain wildcard '*' that can be considered as a regular expression:
+
+```bash
+# The resource is all objects within the container within Root namespace
+native:object//HRwWbb1bJjRms33kkA21hy4JdPfARaH3fW9NfuNN6Fgj/*
+```
+
+If an incoming request has such a resource name, then names are matched:
+
+```bash
+# The resource is all objects within the container within Root namespace
+native:object//HRwWbb1bJjRms33kkA21hy4JdPfARaH3fW9NfuNN6Fgj/EbxzAdz5LB4uqxuz6crWKAumBNtZyK2rKsqQP7TdZvwr
+```
+
+If the incoming request has such a resource name that specifies a container's object within namespace, for instance, `namespicy`,
+then matching does not work out:
+
+```bash
+# The resource is all objects within the container within `namespicy` namespace:
+native:object/namespicy/HRwWbb1bJjRms33kkA21hy4JdPfARaH3fW9NfuNN6Fgj/EbxzAdz5LB4uqxuz6crWKAumBNtZyK2rKsqQP7TdZvwr
+```
+
+##### Engine
+
+`Engine` is trying to match the request against **the target** looking up chain rules, firstly, in `LocalOverrideStorage` (these rules are also known as *local overrides*) and then in `MorphRuleChainStorage` (contract `Policy`). Both storages iterate chain rules according to the specified priority of the targets: `namespace` -> `container` -> `user` -> `groups`.
+
+#### Diagrams
+
+The diagram demonstrates a scenario in Storage node. The request `A` cannot be performed as APE matched
+the request and returned `Access Denied` status. The request `B` is allowed and the client gets `OK` status.
+![Storage node](images/ape/storage_node_ape.svg)
+
+The diagram demonstrates a complex scenario with S3, IAM and Storage node.
+![S3 and IAM](images/ape/s3_ape.svg)
diff --git a/docs/images/ape/s3_ape.puml b/docs/images/ape/s3_ape.puml
new file mode 100644
index 0000000..cf4e2ec
--- /dev/null
+++ b/docs/images/ape/s3_ape.puml
@@ -0,0 +1,61 @@
+@startuml s3 ape
+
+participant "Client" as client
+
+participant "IAM" as iam
+participant "IAM -> APE converter" as converter
+
+box "S3" #HotPink
+ participant "S3 gateway" as s3
+end box
+
+box "Access Policy Engine (as s3 middleware)" #LightPink
+ participant "Local override storage" as s3localOverrides
+ participant "Chain router" as s3chainRouter
+end box
+
+box "Policy contract (shared)"
+ participant "Morph rule storage" as morphRuleStorage
+end box
+
+box "Access Policy Engine (as storage middleware)" #LightGreen
+ participant "Chain Router" as storageChainRouter
+ participant "Local override storage" as storageLocalOverrides
+end box
+
+box "Storage node" #Green
+ participant "Object service" as obj
+ participant "Control service" as control
+end box
+
+group Request IAM to set a policy
+ client -> iam : Set IAM policy
+ iam -> converter : Convert IAM policy
+ converter -> iam : Return APE chain
+ iam -> morphRuleStorage : Store IAM policy and APE chain
+ iam -> s3localOverrides : Set S3 local overrides
+ iam -> client : OK
+end
+
+group Request S3 to set a policy
+ client -> s3 : Set bucket policy
+ s3 -> converter : Convert IAM policy
+ converter -> s3 : Return APE chain
+ s3 -> morphRuleStorage : Store bucket policy and APE chain
+ s3 -> client : OK
+end
+
+group Get object
+ client -> s3: GetObject
+ s3 -> s3chainRouter: Check if APE allows request for S3
+ note over s3chainRouter: matching the request with overrides and rules
+ s3chainRouter -> s3: Status: ALLOW
+ s3 -> obj: Get object
+ obj -> storageChainRouter: Check if APE allows the request
+ note over storageChainRouter : matching the request with overrides and rules
+ storageChainRouter -> obj: Status: ALLOW
+ obj -> s3: Response: OK, Object
+ s3 -> client: Response: OK, Object
+end
+
+@enduml
\ No newline at end of file
diff --git a/docs/images/ape/s3_ape.svg b/docs/images/ape/s3_ape.svg
new file mode 100644
index 0000000..bd119c0
--- /dev/null
+++ b/docs/images/ape/s3_ape.svg
@@ -0,0 +1,73 @@
+
\ No newline at end of file
diff --git a/docs/images/ape/storage_node_ape.puml b/docs/images/ape/storage_node_ape.puml
new file mode 100644
index 0000000..ddf55e3
--- /dev/null
+++ b/docs/images/ape/storage_node_ape.puml
@@ -0,0 +1,46 @@
+@startuml storage node ape
+!pragma teoz true
+
+participant "Administrator" as administrator
+participant "Client" as client
+
+box "Storage node" #Green
+ participant "Object service" as obj
+ participant "Control service" as control
+end box
+
+box "Access Policy Engine" #LightGreen
+ participant "Local override storage" as localOverrides
+ participant "Chain Router" as chainRouter
+ participant "Morph rule storage" as morphRuleStorage
+end box
+
+group Set local override
+ client -> control: Add local override
+ control -> localOverrides: Save override in DB
+ localOverrides -> control: OK
+ control -> client: OK
+end
+
+group Update state in Policy contract
+ administrator -> morphRuleStorage: Add chain
+ morphRuleStorage -> administrator: OK
+end
+
+group Perform a request A
+ client -> obj : Sending a request
+ obj -> chainRouter: Check if APE allows the request
+ note over chainRouter : Fetches local overrides and rules defined for a target/targets and looks for a match
+ chainRouter -> obj: APE returns status: "ACCESS DENIED"
+ obj -> client: Response: "the request is denied"
+end
+
+group Perform a request B
+ client -> obj : Sending a request
+ obj -> chainRouter: Check if APE allows the request
+ note over chainRouter : Fetches local overrides and rules defined for a target/targets and looks for a match
+ chainRouter -> obj: APE returns status: "ALLOW"
+ obj -> client: Response: "OK"
+end
+
+@enduml
\ No newline at end of file
diff --git a/docs/images/ape/storage_node_ape.svg b/docs/images/ape/storage_node_ape.svg
new file mode 100644
index 0000000..6e84081
--- /dev/null
+++ b/docs/images/ape/storage_node_ape.svg
@@ -0,0 +1,58 @@
+
\ No newline at end of file