diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0b774f8362..f3d880cfd2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -299,6 +299,7 @@ apidsl(
   toxcore/tox.api.h)
 add_module(toxcore
   toxcore/misc_tools.h
+  toxcore/tox_api.c
   toxcore/tox.c
   toxcore/tox.h)
 target_link_modules(toxcore toxgroup)
diff --git a/auto_tests/encryptsave_test.c b/auto_tests/encryptsave_test.c
index ec98797c50..22c585ed9e 100644
--- a/auto_tests/encryptsave_test.c
+++ b/auto_tests/encryptsave_test.c
@@ -77,14 +77,12 @@ START_TEST(test_save_friend)
     ck_assert_msg(ret, "failed to encrypted save: %u", error1);
     ck_assert_msg(tox_is_data_encrypted(enc_data), "magic number missing");
 
-    struct Tox_Options options;
-    tox_options_default(&options);
-    options.savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
-    options.savedata_data = enc_data;
-    options.savedata_length = size2;
+    struct Tox_Options *options = tox_options_new(NULL);
+    tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
+    tox_options_set_savedata_data(options, enc_data, size2);
 
     TOX_ERR_NEW err2;
-    Tox *tox3 = tox_new_log(&options, &err2, 0);
+    Tox *tox3 = tox_new_log(options, &err2, 0);
     ck_assert_msg(err2 == TOX_ERR_NEW_LOAD_ENCRYPTED, "wrong error! %u. should fail with %u", err2,
                   TOX_ERR_NEW_LOAD_ENCRYPTED);
     ck_assert_msg(tox3 == NULL, "tox_new with error should return NULL");
@@ -92,9 +90,8 @@ START_TEST(test_save_friend)
     TOX_ERR_DECRYPTION err3;
     ret = tox_pass_decrypt(enc_data, size2, (const uint8_t *)"correcthorsebatterystaple", 25, dec_data, &err3);
     ck_assert_msg(ret, "failed to decrypt save: %u", err3);
-    options.savedata_data = dec_data;
-    options.savedata_length = size;
-    tox3 = tox_new_log(&options, &err2, 0);
+    tox_options_set_savedata_data(options, dec_data, size);
+    tox3 = tox_new_log(options, &err2, 0);
     ck_assert_msg(err2 == TOX_ERR_NEW_OK, "failed to load from decrypted data: %u", err2);
     uint8_t address2[TOX_PUBLIC_KEY_SIZE];
     ret = tox_friend_get_public_key(tox3, 0, address2, 0);
@@ -123,9 +120,8 @@ START_TEST(test_save_friend)
 
     // and now with the code in use (I only bothered with manually to debug this, and it seems a waste
     // to remove the manual check now that it's there)
-    options.savedata_data = out1;
-    options.savedata_length = size;
-    Tox *tox4 = tox_new_log(&options, &err2, 0);
+    tox_options_set_savedata_data(options, out1, size);
+    Tox *tox4 = tox_new_log(options, &err2, 0);
     ck_assert_msg(err2 == TOX_ERR_NEW_OK, "failed to new the third");
     uint8_t address5[TOX_PUBLIC_KEY_SIZE];
     ret = tox_friend_get_public_key(tox4, 0, address5, 0);
@@ -133,6 +129,7 @@ START_TEST(test_save_friend)
     ck_assert_msg(memcmp(address, address2, TOX_PUBLIC_KEY_SIZE) == 0, "addresses don't match! the third");
 
     tox_pass_key_free(key);
+    tox_options_free(options);
 
     tox_kill(tox1);
     tox_kill(tox2);
diff --git a/auto_tests/helpers.h b/auto_tests/helpers.h
index 99930e90d0..5cec575c3a 100644
--- a/auto_tests/helpers.h
+++ b/auto_tests/helpers.h
@@ -3,6 +3,7 @@
 
 #include "../toxcore/tox.h"
 
+#include <assert.h>
 #include <check.h>
 #include <stdio.h>
 
@@ -50,16 +51,22 @@ static void print_debug_log(Tox *m, TOX_LOG_LEVEL level, const char *path, uint3
 
 Tox *tox_new_log(struct Tox_Options *options, TOX_ERR_NEW *err, void *log_user_data)
 {
-    struct Tox_Options *my_options = tox_options_new(NULL);
+    struct Tox_Options *log_options = options;
 
-    if (options != NULL) {
-        *my_options = *options;
+    if (log_options == NULL) {
+        log_options = tox_options_new(NULL);
+    }
+
+    assert(log_options != NULL);
+
+    tox_options_set_log_callback(log_options, &print_debug_log);
+    tox_options_set_log_user_data(log_options, log_user_data);
+    Tox *tox = tox_new(log_options, err);
+
+    if (options == NULL) {
+        tox_options_free(log_options);
     }
 
-    tox_options_set_log_callback(my_options, &print_debug_log);
-    tox_options_set_log_user_data(my_options, log_user_data);
-    Tox *tox = tox_new(my_options, err);
-    tox_options_free(my_options);
     return tox;
 }
 
diff --git a/auto_tests/save_friend_test.c b/auto_tests/save_friend_test.c
index db59a24ad0..9d36ff2d18 100644
--- a/auto_tests/save_friend_test.c
+++ b/auto_tests/save_friend_test.c
@@ -1,7 +1,7 @@
 /* Auto Tests: Save and load friends.
  */
 
-#include "../toxcore/tox.h"
+#include "helpers.h"
 
 #include <assert.h>
 #include <stdio.h>
@@ -51,8 +51,8 @@ void statuschange_callback(Tox *tox, uint32_t friend_number, const uint8_t *mess
 
 int main(int argc, char *argv[])
 {
-    Tox *tox1 = tox_new(tox_options_new(NULL), 0);
-    Tox *tox2 = tox_new(tox_options_new(NULL), 0);
+    Tox *tox1 = tox_new_log(0, 0, 0);
+    Tox *tox2 = tox_new_log(0, 0, 0);
 
     struct test_data to_compare = { { 0 } };
 
@@ -106,13 +106,11 @@ int main(int argc, char *argv[])
     uint8_t savedata[save_size];
     tox_get_savedata(tox1, savedata);
 
-    struct Tox_Options options;
-    tox_options_default(&options);
-    options.savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
-    options.savedata_data = savedata;
-    options.savedata_length = save_size;
+    struct Tox_Options *options = tox_options_new(NULL);
+    tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
+    tox_options_set_savedata_data(options, savedata, save_size);
 
-    Tox *tox_to_compare = tox_new(&options, 0);
+    Tox *tox_to_compare = tox_new(options, 0);
 
     tox_friend_get_name(tox_to_compare, 0, to_compare.name, 0);
     tox_friend_get_status_message(tox_to_compare, 0, to_compare.status_message, 0);
@@ -120,6 +118,7 @@ int main(int argc, char *argv[])
     assert(memcmp(reference_name, to_compare.name, TOX_MAX_NAME_LENGTH) == 0);
     assert(memcmp(reference_status, to_compare.status_message, TOX_MAX_STATUS_MESSAGE_LENGTH) == 0);
 
+    tox_options_free(options);
     tox_kill(tox1);
     tox_kill(tox2);
     tox_kill(tox_to_compare);
diff --git a/auto_tests/tox_many_tcp_test.c b/auto_tests/tox_many_tcp_test.c
index f802bf57c5..197c6e477e 100644
--- a/auto_tests/tox_many_tcp_test.c
+++ b/auto_tests/tox_many_tcp_test.c
@@ -55,17 +55,16 @@ START_TEST(test_many_clients_tcp)
     uint32_t to_comp = 974536;
 
     for (i = 0; i < NUM_TOXES_TCP; ++i) {
-        struct Tox_Options opts;
-        tox_options_default(&opts);
+        struct Tox_Options *opts = tox_options_new(NULL);
 
         if (i == 0) {
-            opts.tcp_port = TCP_RELAY_PORT;
+            tox_options_set_tcp_port(opts, TCP_RELAY_PORT);
         } else {
-            opts.udp_enabled = 0;
+            tox_options_set_udp_enabled(opts, 0);
         }
 
         index[i] = i + 1;
-        toxes[i] = tox_new_log(&opts, 0, &index[i]);
+        toxes[i] = tox_new_log(opts, 0, &index[i]);
         ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i);
         tox_callback_friend_request(toxes[i], accept_friend_request);
         uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
@@ -74,6 +73,8 @@ START_TEST(test_many_clients_tcp)
         ck_assert_msg(tox_add_tcp_relay(toxes[i], TOX_LOCALHOST, TCP_RELAY_PORT, dpk, &error), "add relay error, %i, %i", i,
                       error);
         ck_assert_msg(tox_bootstrap(toxes[i], TOX_LOCALHOST, 33445, dpk, 0), "Bootstrap error");
+
+        tox_options_free(opts);
     }
 
     {
@@ -156,17 +157,16 @@ START_TEST(test_many_clients_tcp_b)
     uint32_t to_comp = 974536;
 
     for (i = 0; i < NUM_TOXES_TCP; ++i) {
-        struct Tox_Options opts;
-        tox_options_default(&opts);
+        struct Tox_Options *opts = tox_options_new(NULL);
 
         if (i < NUM_TCP_RELAYS) {
-            opts.tcp_port = TCP_RELAY_PORT + i;
+            tox_options_set_tcp_port(opts, TCP_RELAY_PORT + i);
         } else {
-            opts.udp_enabled = 0;
+            tox_options_set_udp_enabled(opts, 0);
         }
 
         index[i] = i + 1;
-        toxes[i] = tox_new_log(&opts, 0, &index[i]);
+        toxes[i] = tox_new_log(opts, 0, &index[i]);
         ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i);
         tox_callback_friend_request(toxes[i], accept_friend_request);
         uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
@@ -175,6 +175,8 @@ START_TEST(test_many_clients_tcp_b)
                       "add relay error");
         tox_self_get_dht_id(toxes[0], dpk);
         ck_assert_msg(tox_bootstrap(toxes[i], TOX_LOCALHOST, 33445, dpk, 0), "Bootstrap error");
+
+        tox_options_free(opts);
     }
 
     {
diff --git a/auto_tests/tox_one_test.c b/auto_tests/tox_one_test.c
index ca5fde01e4..8726d5c535 100644
--- a/auto_tests/tox_one_test.c
+++ b/auto_tests/tox_one_test.c
@@ -29,16 +29,6 @@ static void set_random_name_and_status_message(Tox *tox, uint8_t *name, uint8_t
 
 START_TEST(test_one)
 {
-    {
-        TOX_ERR_OPTIONS_NEW o_err;
-        struct Tox_Options *o1 = tox_options_new(&o_err);
-        struct Tox_Options o2;
-        tox_options_default(&o2);
-        ck_assert_msg(o_err == TOX_ERR_OPTIONS_NEW_OK, "tox_options_new wrong error");
-        ck_assert_msg(memcmp(o1, &o2, sizeof(struct Tox_Options)) == 0, "tox_options_new error");
-        tox_options_free(o1);
-    }
-
     uint8_t name[TOX_MAX_NAME_LENGTH];
     uint8_t status_message[TOX_MAX_STATUS_MESSAGE_LENGTH];
 
@@ -93,12 +83,10 @@ START_TEST(test_one)
     tox_kill(tox2);
     TOX_ERR_NEW err_n;
 
-    struct Tox_Options options;
-    tox_options_default(&options);
-    options.savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
-    options.savedata_data = data;
-    options.savedata_length = save_size;
-    tox2 = tox_new_log(&options, &err_n, &index[1]);
+    struct Tox_Options *options = tox_options_new(NULL);
+    tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
+    tox_options_set_savedata_data(options, data, save_size);
+    tox2 = tox_new_log(options, &err_n, &index[1]);
     ck_assert_msg(err_n == TOX_ERR_NEW_OK, "Load failed");
 
     ck_assert_msg(tox_self_get_name_size(tox2) == sizeof name, "Wrong name size.");
@@ -123,11 +111,10 @@ START_TEST(test_one)
     tox_self_get_secret_key(tox2, sk);
     tox_kill(tox2);
 
-    tox_options_default(&options);
-    options.savedata_type = TOX_SAVEDATA_TYPE_SECRET_KEY;
-    options.savedata_data = sk;
-    options.savedata_length = sizeof(sk);
-    tox2 = tox_new_log(&options, &err_n, &index[1]);
+    tox_options_default(options);
+    tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_SECRET_KEY);
+    tox_options_set_savedata_data(options, sk, sizeof(sk));
+    tox2 = tox_new_log(options, &err_n, &index[1]);
     ck_assert_msg(err_n == TOX_ERR_NEW_OK, "Load failed");
     uint8_t address3[TOX_ADDRESS_SIZE];
     tox_self_get_address(tox2, address3);
@@ -142,6 +129,7 @@ START_TEST(test_one)
         ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
     }
 
+    tox_options_free(options);
     tox_kill(tox1);
     tox_kill(tox2);
 }
diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c
index 2faa8cad32..dfd1d80a30 100644
--- a/auto_tests/tox_test.c
+++ b/auto_tests/tox_test.c
@@ -418,12 +418,10 @@ START_TEST(test_few_clients)
     tox_get_savedata(tox2, save1);
     tox_kill(tox2);
 
-    struct Tox_Options options;
-    tox_options_default(&options);
-    options.savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
-    options.savedata_data = save1;
-    options.savedata_length = save_size1;
-    tox2 = tox_new_log(&options, NULL, &index[1]);
+    struct Tox_Options *options = tox_options_new(NULL);
+    tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
+    tox_options_set_savedata_data(options, save1, save_size1);
+    tox2 = tox_new_log(options, NULL, &index[1]);
     cur_time = time(NULL);
     off = 1;
 
@@ -727,6 +725,7 @@ START_TEST(test_few_clients)
 
     printf("test_few_clients succeeded, took %llu seconds\n", time(NULL) - cur_time);
 
+    tox_options_free(options);
     tox_kill(tox1);
     tox_kill(tox2);
     tox_kill(tox3);
diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc
index f8f6f9cf2a..84e24ebda2 100644
--- a/toxcore/Makefile.inc
+++ b/toxcore/Makefile.inc
@@ -27,6 +27,7 @@ libtoxcore_la_SOURCES = ../toxcore/DHT.h \
                         ../toxcore/ping.c \
                         ../toxcore/tox.h \
                         ../toxcore/tox.c \
+                        ../toxcore/tox_api.c \
                         ../toxcore/util.h \
                         ../toxcore/util.c \
                         ../toxcore/group.h \
diff --git a/toxcore/tox.c b/toxcore/tox.c
index 7a9a708cfd..37298ce23c 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -69,20 +69,6 @@ typedef struct Messenger Tox;
 #error TOX_MAX_STATUS_MESSAGE_LENGTH is assumed to be equal to MAX_STATUSMESSAGE_LENGTH
 #endif
 
-uint32_t tox_version_major(void)
-{
-    return TOX_VERSION_MAJOR;
-}
-
-uint32_t tox_version_minor(void)
-{
-    return TOX_VERSION_MINOR;
-}
-
-uint32_t tox_version_patch(void)
-{
-    return TOX_VERSION_PATCH;
-}
 
 bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch)
 {
@@ -90,93 +76,6 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch)
 }
 
 
-#define CONST_FUNCTION(lowercase, uppercase) \
-uint32_t tox_##lowercase(void) \
-{ \
-    return TOX_##uppercase; \
-}
-
-CONST_FUNCTION(public_key_size, PUBLIC_KEY_SIZE)
-CONST_FUNCTION(secret_key_size, SECRET_KEY_SIZE)
-CONST_FUNCTION(address_size, ADDRESS_SIZE)
-CONST_FUNCTION(max_name_length, MAX_NAME_LENGTH)
-CONST_FUNCTION(max_status_message_length, MAX_STATUS_MESSAGE_LENGTH)
-CONST_FUNCTION(max_friend_request_length, MAX_FRIEND_REQUEST_LENGTH)
-CONST_FUNCTION(max_message_length, MAX_MESSAGE_LENGTH)
-CONST_FUNCTION(max_custom_packet_size, MAX_CUSTOM_PACKET_SIZE)
-CONST_FUNCTION(hash_length, HASH_LENGTH)
-CONST_FUNCTION(file_id_length, FILE_ID_LENGTH)
-CONST_FUNCTION(max_filename_length, MAX_FILENAME_LENGTH)
-
-
-#define ACCESSORS(type, ns, name) \
-type tox_options_get_##ns##name(const struct Tox_Options *options) \
-{ \
-    return options->ns##name; \
-} \
-void tox_options_set_##ns##name(struct Tox_Options *options, type name) \
-{ \
-    options->ns##name = name; \
-}
-
-ACCESSORS(bool, , ipv6_enabled)
-ACCESSORS(bool, , udp_enabled)
-ACCESSORS(TOX_PROXY_TYPE, proxy_ , type)
-ACCESSORS(const char *, proxy_ , host)
-ACCESSORS(uint16_t, proxy_ , port)
-ACCESSORS(uint16_t, , start_port)
-ACCESSORS(uint16_t, , end_port)
-ACCESSORS(uint16_t, , tcp_port)
-ACCESSORS(bool, , hole_punching_enabled)
-ACCESSORS(TOX_SAVEDATA_TYPE, savedata_, type)
-ACCESSORS(size_t, savedata_, length)
-ACCESSORS(tox_log_cb *, log_, callback)
-ACCESSORS(void *, log_, user_data)
-ACCESSORS(bool, , local_discovery_enabled)
-
-const uint8_t *tox_options_get_savedata_data(const struct Tox_Options *options)
-{
-    return options->savedata_data;
-}
-
-void tox_options_set_savedata_data(struct Tox_Options *options, const uint8_t *data, size_t length)
-{
-    options->savedata_data = data;
-    options->savedata_length = length;
-}
-
-
-void tox_options_default(struct Tox_Options *options)
-{
-    if (options) {
-        memset(options, 0, sizeof(struct Tox_Options));
-        options->ipv6_enabled = 1;
-        options->udp_enabled = 1;
-        options->proxy_type = TOX_PROXY_TYPE_NONE;
-        options->hole_punching_enabled = true;
-        options->local_discovery_enabled = true;
-    }
-}
-
-struct Tox_Options *tox_options_new(TOX_ERR_OPTIONS_NEW *error)
-{
-    struct Tox_Options *options = (struct Tox_Options *)calloc(sizeof(struct Tox_Options), 1);
-
-    if (options) {
-        tox_options_default(options);
-        SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_OK);
-        return options;
-    }
-
-    SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_MALLOC);
-    return NULL;
-}
-
-void tox_options_free(struct Tox_Options *options)
-{
-    free(options);
-}
-
 Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error)
 {
     Messenger_Options m_options = {0};
@@ -186,27 +85,27 @@ Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error)
     if (options == NULL) {
         m_options.ipv6enabled = TOX_ENABLE_IPV6_DEFAULT;
     } else {
-        if (options->savedata_type != TOX_SAVEDATA_TYPE_NONE) {
-            if (options->savedata_data == NULL || options->savedata_length == 0) {
+        if (tox_options_get_savedata_type(options) != TOX_SAVEDATA_TYPE_NONE) {
+            if (tox_options_get_savedata_data(options) == NULL || tox_options_get_savedata_length(options) == 0) {
                 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
                 return NULL;
             }
         }
 
-        if (options->savedata_type == TOX_SAVEDATA_TYPE_SECRET_KEY) {
-            if (options->savedata_length != TOX_SECRET_KEY_SIZE) {
+        if (tox_options_get_savedata_type(options) == TOX_SAVEDATA_TYPE_SECRET_KEY) {
+            if (tox_options_get_savedata_length(options) != TOX_SECRET_KEY_SIZE) {
                 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
                 return NULL;
             }
 
             load_savedata_sk = 1;
-        } else if (options->savedata_type == TOX_SAVEDATA_TYPE_TOX_SAVE) {
-            if (options->savedata_length < TOX_ENC_SAVE_MAGIC_LENGTH) {
+        } else if (tox_options_get_savedata_type(options) == TOX_SAVEDATA_TYPE_TOX_SAVE) {
+            if (tox_options_get_savedata_length(options) < TOX_ENC_SAVE_MAGIC_LENGTH) {
                 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
                 return NULL;
             }
 
-            if (crypto_memcmp(options->savedata_data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) {
+            if (crypto_memcmp(tox_options_get_savedata_data(options), TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) {
                 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_ENCRYPTED);
                 return NULL;
             }
@@ -214,18 +113,18 @@ Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error)
             load_savedata_tox = 1;
         }
 
-        m_options.ipv6enabled = options->ipv6_enabled;
-        m_options.udp_disabled = !options->udp_enabled;
-        m_options.port_range[0] = options->start_port;
-        m_options.port_range[1] = options->end_port;
-        m_options.tcp_server_port = options->tcp_port;
-        m_options.hole_punching_enabled = options->hole_punching_enabled;
-        m_options.local_discovery_enabled = options->local_discovery_enabled;
+        m_options.ipv6enabled = tox_options_get_ipv6_enabled(options);
+        m_options.udp_disabled = !tox_options_get_udp_enabled(options);
+        m_options.port_range[0] = tox_options_get_start_port(options);
+        m_options.port_range[1] = tox_options_get_end_port(options);
+        m_options.tcp_server_port = tox_options_get_tcp_port(options);
+        m_options.hole_punching_enabled = tox_options_get_hole_punching_enabled(options);
+        m_options.local_discovery_enabled = tox_options_get_local_discovery_enabled(options);
 
-        m_options.log_callback = (logger_cb *)options->log_callback;
-        m_options.log_user_data = options->log_user_data;
+        m_options.log_callback = (logger_cb *)tox_options_get_log_callback(options);
+        m_options.log_user_data = tox_options_get_log_user_data(options);
 
-        switch (options->proxy_type) {
+        switch (tox_options_get_proxy_type(options)) {
             case TOX_PROXY_TYPE_HTTP:
                 m_options.proxy_info.proxy_type = TCP_PROXY_HTTP;
                 break;
@@ -244,7 +143,7 @@ Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error)
         }
 
         if (m_options.proxy_info.proxy_type != TCP_PROXY_NONE) {
-            if (options->proxy_port == 0) {
+            if (tox_options_get_proxy_port(options) == 0) {
                 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_PORT);
                 return NULL;
             }
@@ -255,13 +154,13 @@ Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error)
                 m_options.proxy_info.ip_port.ip.family = AF_UNSPEC;
             }
 
-            if (!addr_resolve_or_parse_ip(options->proxy_host, &m_options.proxy_info.ip_port.ip, NULL)) {
+            if (!addr_resolve_or_parse_ip(tox_options_get_proxy_host(options), &m_options.proxy_info.ip_port.ip, NULL)) {
                 SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_HOST);
                 // TODO(irungentoo): TOX_ERR_NEW_PROXY_NOT_FOUND if domain.
                 return NULL;
             }
 
-            m_options.proxy_info.ip_port.port = htons(options->proxy_port);
+            m_options.proxy_info.ip_port.port = htons(tox_options_get_proxy_port(options));
         }
     }
 
@@ -282,10 +181,11 @@ Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error)
         return NULL;
     }
 
-    if (load_savedata_tox && messenger_load(m, options->savedata_data, options->savedata_length) == -1) {
+    if (load_savedata_tox
+            && messenger_load(m, tox_options_get_savedata_data(options), tox_options_get_savedata_length(options)) == -1) {
         SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
     } else if (load_savedata_sk) {
-        load_secret_key(m->net_crypto, options->savedata_data);
+        load_secret_key(m->net_crypto, tox_options_get_savedata_data(options));
         SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
     } else {
         SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
diff --git a/toxcore/tox_api.c b/toxcore/tox_api.c
new file mode 100644
index 0000000000..b6c8c38618
--- /dev/null
+++ b/toxcore/tox_api.c
@@ -0,0 +1,97 @@
+#include "tox.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}}
+
+
+#define CONST_FUNCTION(lowercase, uppercase) \
+uint32_t tox_##lowercase(void) \
+{ \
+    return TOX_##uppercase; \
+}
+
+CONST_FUNCTION(version_major, VERSION_MAJOR)
+CONST_FUNCTION(version_minor, VERSION_MINOR)
+CONST_FUNCTION(version_patch, VERSION_PATCH)
+CONST_FUNCTION(public_key_size, PUBLIC_KEY_SIZE)
+CONST_FUNCTION(secret_key_size, SECRET_KEY_SIZE)
+CONST_FUNCTION(address_size, ADDRESS_SIZE)
+CONST_FUNCTION(max_name_length, MAX_NAME_LENGTH)
+CONST_FUNCTION(max_status_message_length, MAX_STATUS_MESSAGE_LENGTH)
+CONST_FUNCTION(max_friend_request_length, MAX_FRIEND_REQUEST_LENGTH)
+CONST_FUNCTION(max_message_length, MAX_MESSAGE_LENGTH)
+CONST_FUNCTION(max_custom_packet_size, MAX_CUSTOM_PACKET_SIZE)
+CONST_FUNCTION(hash_length, HASH_LENGTH)
+CONST_FUNCTION(file_id_length, FILE_ID_LENGTH)
+CONST_FUNCTION(max_filename_length, MAX_FILENAME_LENGTH)
+
+
+#define ACCESSORS(type, ns, name) \
+type tox_options_get_##ns##name(const struct Tox_Options *options) \
+{ \
+    return options->ns##name; \
+} \
+void tox_options_set_##ns##name(struct Tox_Options *options, type name) \
+{ \
+    options->ns##name = name; \
+}
+
+ACCESSORS(bool, , ipv6_enabled)
+ACCESSORS(bool, , udp_enabled)
+ACCESSORS(TOX_PROXY_TYPE, proxy_ , type)
+ACCESSORS(const char *, proxy_ , host)
+ACCESSORS(uint16_t, proxy_ , port)
+ACCESSORS(uint16_t, , start_port)
+ACCESSORS(uint16_t, , end_port)
+ACCESSORS(uint16_t, , tcp_port)
+ACCESSORS(bool, , hole_punching_enabled)
+ACCESSORS(TOX_SAVEDATA_TYPE, savedata_, type)
+ACCESSORS(size_t, savedata_, length)
+ACCESSORS(tox_log_cb *, log_, callback)
+ACCESSORS(void *, log_, user_data)
+ACCESSORS(bool, , local_discovery_enabled)
+
+const uint8_t *tox_options_get_savedata_data(const struct Tox_Options *options)
+{
+    return options->savedata_data;
+}
+
+void tox_options_set_savedata_data(struct Tox_Options *options, const uint8_t *data, size_t length)
+{
+    options->savedata_data = data;
+    options->savedata_length = length;
+}
+
+void tox_options_default(struct Tox_Options *options)
+{
+    if (options) {
+        struct Tox_Options default_options = { 0 };
+        *options = default_options;
+        tox_options_set_ipv6_enabled(options, true);
+        tox_options_set_udp_enabled(options, true);
+        tox_options_set_proxy_type(options, TOX_PROXY_TYPE_NONE);
+        tox_options_set_hole_punching_enabled(options, true);
+        tox_options_set_local_discovery_enabled(options, true);
+    }
+}
+
+struct Tox_Options *tox_options_new(TOX_ERR_OPTIONS_NEW *error)
+{
+    struct Tox_Options *options = (struct Tox_Options *)malloc(sizeof(struct Tox_Options));
+
+    if (options) {
+        tox_options_default(options);
+        SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_OK);
+        return options;
+    }
+
+    SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_MALLOC);
+    return NULL;
+}
+
+void tox_options_free(struct Tox_Options *options)
+{
+    free(options);
+}