diff --git a/index.js b/index.js
new file mode 100644
index 0000000..5db1bc1
--- /dev/null
+++ b/index.js
@@ -0,0 +1,171 @@
+const DEFAULT_CORE_REQUEST_TIMEOUT = 5 * 1000;
+const MAX_REPORT_RETRY = 30;
+const REPORT_RETRY_SLEEP_MS = 2000;
+
+const axios = require('axios').default;
+
+const config = require('komodo-sdk/config');
+const coreUrl = require('komodo-sdk/core-url');
+const logger = require('komodo-sdk/logger');
+
+let partner;
+let first = true;
+let coreIsHealthy = null;
+let skipNext = 0;
+
+const DEFAULT_CORE_AXIOS_CONFIG = {
+    headers: { 'Content-Type': 'application/json' },
+    timeout: config.core_request_timeout || config.request_timeout || DEFAULT_CORE_REQUEST_TIMEOUT,
+};
+
+const GET_TASK_AXIOS_CONFIG = DEFAULT_CORE_AXIOS_CONFIG;
+const REPORT_AXIOS_CONFIG = DEFAULT_CORE_AXIOS_CONFIG;
+
+function detectCoreStatusChange(isHealthy, url, err) {
+    if (coreIsHealthy !== isHealthy) {
+        coreIsHealthy = isHealthy;
+
+        if (isHealthy) {
+            logger.info('POSTPAID2-SDK: CORE is healthy now', { url, err: err && err.message });
+        } else {
+            logger.warn('POSTPAID2-SDK: CORE is unhealthy now', { url, err: err && err.message });
+        }
+    }
+}
+
+async function getTask() {
+    if (!partner) return;
+
+    if (skipNext > 0) {
+        skipNext -= 1;
+        return;
+    }
+
+    if (first) {
+        first = false;
+        logger.verbose('POSTPAID2-SDK: first pull request to CORE');
+    }
+
+    const coreEndpoint = `${coreUrl}/postpaid2/task`;
+
+    const payload = {
+        handler: config.handler || config.handler_name,
+        products: config.products || [],
+    };
+
+    let task;
+    try {
+        const result = await axios.post(
+            coreEndpoint, payload, GET_TASK_AXIOS_CONFIG,
+        );
+
+        if (!result || !result.data) throw new Error('POSTPAID2-SDK: Empty CORE response on pulling task. MARK-26F332C6');
+        if (result && result.data && result.data.task && !result.data.task.postpaid) throw new Error('POSTPAID2-SDK: CORE returning non postpaid task on pulling task. MARK-B338CEF8');
+
+        detectCoreStatusChange(true, coreEndpoint);
+        task = result.data.task;
+    } catch (e) {
+        skipNext = 3;
+        detectCoreStatusChange(false, coreEndpoint, e);
+    }
+
+    if (!task) return;
+
+    task.remote_product = ((config.remote_products || {})[task.product]) || task.product;
+
+    logger.verbose('POSTPAID2-SDK: Got task from CORE on pulling task', { task });
+
+    if (task.inquiry_only) {
+        if (typeof partner.inquiry === 'function') partner.inquiry(task);
+        return;
+    }
+
+    if (typeof partner.pay === 'function') partner.pay(task);
+}
+
+const getTaskLooper = async () => {
+    await getTask();
+
+    setTimeout(() => {
+        getTaskLooper();
+    }, config.pull_interval_ms || 1000);
+};
+
+exports.setPartner = (val) => {
+    partner = val;
+    setInterval(getTaskLooper, config.pull_interval_ms || 1000);
+};
+
+exports.report = async (data, xid, retry) => {
+    if (!data.trx_id) {
+        logger.warn('POSTPAID2-SDK: INVALID DATA TO REPORT. No trx id in report. MARK-3A37B7CA', { xid, data });
+        return;
+    }
+
+    if (!data.rc || typeof data.rc !== 'string') {
+        logger.warn('POSTPAID2-SDK: INVALID DATA TO REPORT. Rc is not valid. MARK-41ED74FC', {
+            xid, trxId: data.trx_id, rc: data.rc, typeofRc: typeof data.rc,
+        });
+    }
+
+    const dataToReport = {
+        handler: config.handler || config.handler_name,
+        command: data.command,
+        trx_id: data.trx_id,
+        rc: data.rc,
+        sn: data.sn,
+        amount: data.amount,
+        base_bill_amount: data.base_bill_amount,
+        bill_count: data.bill_count,
+        message: data.message,
+        info: data.info,
+        detail: data.detail,
+        data: data.data,
+    };
+
+    logger.verbose('POSTPAID2-SDK: Going to report to CORE', {
+        xid,
+        trxId: data.trx_id,
+        rc: data.rc,
+        sn: data.sn,
+        amount: data.amount,
+        baseBillAmount: data.base_bill_amount,
+    });
+
+    const coreEndpoint = `${coreUrl}/postpaid2/report`;
+
+    try {
+        const reportResult = await axios.post(
+            coreEndpoint, JSON.stringify(dataToReport), REPORT_AXIOS_CONFIG,
+        );
+
+        if (!reportResult) {
+            logger.warn('POSTPAID2-SDK: unknown result from CORE on reporting trx result. MARK-795C53DB');
+        }
+    } catch (e) {
+        const newRetry = (retry || 0) + 1;
+        logger.warn('POSTPAID2-SDK: Exception on reporting trx result to CORE. MARK-E7F000D8', {
+            xid, err: e.message, retry: newRetry, maxRetry: MAX_REPORT_RETRY,
+        });
+
+        if (!this || !this.report) {
+            logger.warn('POSTPAID2-SDK: Can not retry report because of unkown this.report!');
+            return;
+        }
+
+        if (newRetry < MAX_REPORT_RETRY) {
+            setTimeout(() => {
+                logger.info('POSTPAID2-SDK: Retrying to send report to CORE', {
+                    xid,
+                    trxId: data.trx_id,
+                    rc: data.rc,
+                    sn: data.sn,
+                    amount: data.amount,
+                    baseBillAmount: data.base_bill_amount,
+                });
+
+                this.report(data, xid, newRetry);
+            }, REPORT_RETRY_SLEEP_MS);
+        }
+    }
+};