diff --git a/MANIFEST.in b/MANIFEST.in
index 20a4406..c1ea444 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,6 +1,6 @@
 include LICENSE
 include README.rst
-include toml.pyi
+include toml/*pyi
 include tox.ini
 include test.toml
 recursive-include tests *.py *.sh
diff --git a/toml.pyi b/toml.pyi
deleted file mode 100644
index fd39468..0000000
--- a/toml.pyi
+++ /dev/null
@@ -1,25 +0,0 @@
-from typing import Any, IO, Mapping, MutableMapping, Optional, Type, Union
-import datetime
-
-
-class TomlDecodeError(Exception): ...
-
-class TomlTz(datetime.tzinfo):
-    def __init__(self, toml_offset: str) -> None: ...
-
-class TomlDecoder(object):...
-
-class TomlEncoder(object):...
-
-class TomlPreserveCommentDecoder(TomlDecoder):...
-
-class TomlPreserveCommentEncoder(TomlEncoder):...
-
-def load(f: Union[str, list, IO[str]],
-         _dict: Type[MutableMapping[str, Any]] = ...) \
-         -> MutableMapping[str, Any]: ...
-def loads(s: str, _dict: Type[MutableMapping[str, Any]] = ...) \
-          -> MutableMapping[str, Any]: ...
-
-def dump(o: Mapping[str, Any], f: IO[str]) -> str: ...
-def dumps(o: Mapping[str, Any]) -> str: ...
diff --git a/toml/__init__.pyi b/toml/__init__.pyi
new file mode 100644
index 0000000..94c20f4
--- /dev/null
+++ b/toml/__init__.pyi
@@ -0,0 +1,15 @@
+from toml import decoder as decoder, encoder as encoder
+
+load = decoder.load
+loads = decoder.loads
+TomlDecoder = decoder.TomlDecoder
+TomlDecodeError = decoder.TomlDecodeError
+TomlPreserveCommentDecoder = decoder.TomlPreserveCommentDecoder
+dump = encoder.dump
+dumps = encoder.dumps
+TomlEncoder = encoder.TomlEncoder
+TomlArraySeparatorEncoder = encoder.TomlArraySeparatorEncoder
+TomlPreserveInlineDictEncoder = encoder.TomlPreserveInlineDictEncoder
+TomlNumpyEncoder = encoder.TomlNumpyEncoder
+TomlPreserveCommentEncoder = encoder.TomlPreserveCommentEncoder
+TomlPathlibEncoder = encoder.TomlPathlibEncoder
diff --git a/toml/decoder.pyi b/toml/decoder.pyi
new file mode 100644
index 0000000..967d3dd
--- /dev/null
+++ b/toml/decoder.pyi
@@ -0,0 +1,52 @@
+from toml.tz import TomlTz as TomlTz
+from typing import Any, Optional
+
+unicode = str
+basestring = str
+unichr = chr
+FNFError = FileNotFoundError
+FNFError = IOError
+TIME_RE: Any
+
+class TomlDecodeError(ValueError):
+    msg: Any = ...
+    doc: Any = ...
+    pos: Any = ...
+    lineno: Any = ...
+    colno: Any = ...
+    def __init__(self, msg: Any, doc: Any, pos: Any) -> None: ...
+
+class CommentValue:
+    val: Any = ...
+    comment: Any = ...
+    def __init__(self, val: Any, comment: Any, beginline: Any, _dict: Any) -> None: ...
+    def __getitem__(self, key: Any): ...
+    def __setitem__(self, key: Any, value: Any) -> None: ...
+    def dump(self, dump_value_func: Any): ...
+
+def load(f: Union[str, list, IO[str]],
+         _dict: Type[MutableMapping[str, Any]] = ...,
+         decoder: TomlDecoder = ...) \
+         -> MutableMapping[str, Any]: ...
+def loads(s: str, _dict: Type[MutableMapping[str, Any]] = ..., decoder: TomlDecoder = ...) \
+         -> MutableMapping[str, Any]: ...
+
+class InlineTableDict: ...
+
+class TomlDecoder:
+    def __init__(self, _dict: Any = ...) -> None: ...
+    def get_empty_table(self): ...
+    def get_empty_inline_table(self): ...
+    def load_inline_object(self, line: Any, currentlevel: Any, multikey: bool = ..., multibackslash: bool = ...) -> None: ...
+    def load_line(self, line: Any, currentlevel: Any, multikey: Any, multibackslash: Any): ...
+    def load_value(self, v: Any, strictly_valid: bool = ...): ...
+    def bounded_string(self, s: Any): ...
+    def load_array(self, a: Any): ...
+    def preserve_comment(self, line_no: Any, key: Any, comment: Any, beginline: Any) -> None: ...
+    def embed_comments(self, idx: Any, currentlevel: Any) -> None: ...
+
+class TomlPreserveCommentDecoder(TomlDecoder):
+    saved_comments: Any = ...
+    def __init__(self, _dict: Any = ...) -> None: ...
+    def preserve_comment(self, line_no: Any, key: Any, comment: Any, beginline: Any) -> None: ...
+    def embed_comments(self, idx: Any, currentlevel: Any) -> None: ...
diff --git a/toml/encoder.pyi b/toml/encoder.pyi
new file mode 100644
index 0000000..194a358
--- /dev/null
+++ b/toml/encoder.pyi
@@ -0,0 +1,34 @@
+from toml.decoder import InlineTableDict as InlineTableDict
+from typing import Any, Optional
+
+unicode = str
+
+def dump(o: Mapping[str, Any], f: IO[str], encoder: TomlEncoder = ...) -> str: ...
+def dumps(o: Mapping[str, Any], encoder: TomlEncoder = ...) -> str: ...
+
+class TomlEncoder:
+    preserve: Any = ...
+    dump_funcs: Any = ...
+    def __init__(self, _dict: Any = ..., preserve: bool = ...): ...
+    def get_empty_table(self): ...
+    def dump_list(self, v: Any): ...
+    def dump_inline_table(self, section: Any): ...
+    def dump_value(self, v: Any): ...
+    def dump_sections(self, o: Any, sup: Any): ...
+
+class TomlPreserveInlineDictEncoder(TomlEncoder):
+    def __init__(self, _dict: Any = ...) -> None: ...
+
+class TomlArraySeparatorEncoder(TomlEncoder):
+    separator: Any = ...
+    def __init__(self, _dict: Any = ..., preserve: bool = ..., separator: str = ...) -> None: ...
+    def dump_list(self, v: Any): ...
+
+class TomlNumpyEncoder(TomlEncoder):
+    def __init__(self, _dict: Any = ..., preserve: bool = ...) -> None: ...
+
+class TomlPreserveCommentEncoder(TomlEncoder):
+    def __init__(self, _dict: Any = ..., preserve: bool = ...): ...
+
+class TomlPathlibEncoder(TomlEncoder):
+    def dump_value(self, v: Any): ...
diff --git a/toml/ordered.pyi b/toml/ordered.pyi
new file mode 100644
index 0000000..0f4292d
--- /dev/null
+++ b/toml/ordered.pyi
@@ -0,0 +1,7 @@
+from toml import TomlDecoder as TomlDecoder, TomlEncoder as TomlEncoder
+
+class TomlOrderedDecoder(TomlDecoder):
+    def __init__(self) -> None: ...
+
+class TomlOrderedEncoder(TomlEncoder):
+    def __init__(self) -> None: ...
diff --git a/toml/tz.pyi b/toml/tz.pyi
new file mode 100644
index 0000000..fe37aea
--- /dev/null
+++ b/toml/tz.pyi
@@ -0,0 +1,9 @@
+from datetime import tzinfo
+from typing import Any
+
+class TomlTz(tzinfo):
+    def __init__(self, toml_offset: Any) -> None: ...
+    def __deepcopy__(self, memo: Any): ...
+    def tzname(self, dt: Any): ...
+    def utcoffset(self, dt: Any): ...
+    def dst(self, dt: Any): ...