Skip to content

Subscriber - Billing ​

Base URL: https://your-domain.com

The signed-in subscriber's own invoices, payments and wallet ledger. Paging, the 404 rule, money and date formats are described under Conventions.


Subscriber Invoices ​

List the subscriber's invoices, newest first. Deleted invoices are not listed.

PropertyValue
EndpointSubscriber Invoices
MethodGET
URL/api/v1/subscriber/invoices
AuthenticationBearer Token (Subscriber)

Request Headers:

HeaderValueRequired
Acceptapplication/jsonYes
AuthorizationBearer subscriber-tokenYes

Query Parameters:

ParameterTypeRequiredDescription
pageintegerNoPage number (default 1)
per_pageintegerNoItems per page, 1 to 50 (default 20)

Request Body: None

Success Response (200 OK):

json
{
    "status": "success",
    "data": [
        {
            "id": 2041,
            "number": "a3f9c1d27b8e4",
            "status": "partial",
            "package_name": "Home Fiber 40",
            "period_start": "2026-10-02T10:12:00+06:00",
            "period_end": "2026-11-01T23:59:00+06:00",
            "due_date": null,
            "total": 1050,
            "paid": 550,
            "due": 500,
            "created_at": "2026-10-02T10:12:00+06:00"
        }
    ],
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 20,
        "total": 1
    }
}

Field notes:

  • number is the invoice's activation reference.
  • status is one of active, disabled, paid, partial, due, reverted, or unknown when the invoice has no status.
  • period_start and period_end are the service period the invoice covers; due_date is the billing due date. Each is null when not set.
  • total is the invoice amount less any migration credit; due is total - paid, never below 0.

Error Response (401 Unauthorized):

json
{
    "message": "Unauthenticated."
}

Code Examples:

bash
curl -X GET "https://your-domain.com/api/v1/subscriber/invoices?page=1&per_page=20" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer your-auth-token"
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('GET', '/api/v1/subscriber/invoices', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'query' => [
        'page'     => 1,
        'per_page' => 20,
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const params = new URLSearchParams({
  page: 1,
  per_page: 20,
});

const response = await fetch(`${BASE_URL}/api/v1/subscriber/invoices?${params}`, {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.get(
    f"{BASE_URL}/api/v1/subscriber/invoices",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    params={
        "page": 1,
        "per_page": 20,
    },
)

data = response.json()
print(data)
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscriber/invoices"

	q := url.Values{}
	q.Set("page", "1")
	q.Set("per_page", "20")
	endpoint += "?" + q.Encode()

	req, _ := http.NewRequest("GET", endpoint, nil)
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .get(format!("{BASE_URL}/api/v1/subscriber/invoices"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .query(&[
            ("page", "1"),
            ("per_page", "20"),
        ])
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Subscriber Invoice Details ​

Get one of the subscriber's invoices with its fee breakdown and linked payment.

PropertyValue
EndpointSubscriber Invoice Details
MethodGET
URL/api/v1/subscriber/invoices/{id}
AuthenticationBearer Token (Subscriber)

Request Headers:

HeaderValueRequired
Acceptapplication/jsonYes
AuthorizationBearer subscriber-tokenYes

Path Parameters:

ParameterTypeRequiredDescription
idintegerYesInvoice ID

Request Body: None

Success Response (200 OK):

json
{
    "status": "success",
    "data": {
        "id": 2041,
        "number": "a3f9c1d27b8e4",
        "status": "partial",
        "package_name": "Home Fiber 40",
        "period_start": "2026-10-02T10:12:00+06:00",
        "period_end": "2026-11-01T23:59:00+06:00",
        "due_date": null,
        "total": 1050,
        "paid": 550,
        "due": 500,
        "created_at": "2026-10-02T10:12:00+06:00",
        "package_fee": 1000,
        "extra_fee_total": 50,
        "activation_extra_fee_total": 0,
        "extra_services_total": 0,
        "discount": 0,
        "payment": {
            "id": 881,
            "transaction_id": "a3f9c1d27b8e4_5c21ab",
            "amount": 550,
            "method": 11,
            "method_label": "Bkash",
            "reverted": false,
            "withdrawal": false,
            "note": null,
            "paid_at": "2026-10-02T10:12:00+06:00"
        }
    }
}

Field notes:

  • The list fields, plus the same breakdown as the portal's invoice page: package_fee + extra_fee_total + activation_extra_fee_total + extra_services_total - discount = total.
  • payment is the invoice's payment (same shape as Subscriber Payment Details), or null when there is none.

Error Response (404 Not Found):

json
{
    "status": "error",
    "message": "Not Found"
}

Code Examples:

bash
curl -X GET "https://your-domain.com/api/v1/subscriber/invoices/1" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer your-auth-token"
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$invoiceId = 1;

$response = $client->request('GET', "/api/v1/subscriber/invoices/{$invoiceId}", [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const invoiceId = 1;

const response = await fetch(`${BASE_URL}/api/v1/subscriber/invoices/${invoiceId}`, {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

invoice_id = 1

response = requests.get(
    f"{BASE_URL}/api/v1/subscriber/invoices/{invoice_id}",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
)

data = response.json()
print(data)
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"strconv"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	invoiceId := 1
	endpoint := baseURL + "/api/v1/subscriber/invoices/" + strconv.Itoa(invoiceId)

	req, _ := http.NewRequest("GET", endpoint, nil)
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();
    let invoice_id = 1;

    let response = client
        .get(format!("{BASE_URL}/api/v1/subscriber/invoices/{invoice_id}"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Subscriber Payments ​

List the subscriber's payments, newest first, with totals across all of them.

PropertyValue
EndpointSubscriber Payments
MethodGET
URL/api/v1/subscriber/payments
AuthenticationBearer Token (Subscriber)

Request Headers:

HeaderValueRequired
Acceptapplication/jsonYes
AuthorizationBearer subscriber-tokenYes

Query Parameters:

ParameterTypeRequiredDescription
pageintegerNoPage number (default 1)
per_pageintegerNoItems per page, 1 to 50 (default 20)

Request Body: None

Success Response (200 OK):

json
{
    "status": "success",
    "data": [
        {
            "id": 881,
            "transaction_id": "a3f9c1d27b8e4_5c21ab",
            "amount": 550,
            "method": 11,
            "method_label": "Bkash",
            "reverted": false,
            "withdrawal": false,
            "note": null,
            "paid_at": "2026-10-02T10:12:00+06:00"
        },
        {
            "id": 812,
            "transaction_id": "7d04be19a6c32",
            "amount": -100,
            "method": 1,
            "method_label": "Cash",
            "reverted": false,
            "withdrawal": true,
            "note": "Refund of overpayment",
            "paid_at": "2026-09-20T16:40:00+06:00"
        }
    ],
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 20,
        "total": 2
    },
    "summary": {
        "net_paid": 450,
        "received": 550,
        "withdrawn": -100,
        "reverted": 0
    }
}

Field notes:

  • method is the stored payment method code and method_label its name as the admin panel shows it (for example 1 Cash, 2 Cheque, 4 Subscriber Balance, 11 Bkash, 12 SSLCommerz). Unlisted codes show as Others.
  • reverted is true when the payment was reversed with its invoice. A reverted payment is still listed but is not counted in net_paid.
  • withdrawal is true for a negative amount (money paid back to the subscriber).
  • summary covers all the subscriber's payments, not only the current page: received is the sum of positive payments, withdrawn the sum of withdrawals (negative), net_paid = received + withdrawn, and reverted the sum of reverted payments.

Error Response (401 Unauthorized):

json
{
    "message": "Unauthenticated."
}

Code Examples:

bash
curl -X GET "https://your-domain.com/api/v1/subscriber/payments?page=1&per_page=20" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer your-auth-token"
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('GET', '/api/v1/subscriber/payments', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'query' => [
        'page'     => 1,
        'per_page' => 20,
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const params = new URLSearchParams({
  page: 1,
  per_page: 20,
});

const response = await fetch(`${BASE_URL}/api/v1/subscriber/payments?${params}`, {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.get(
    f"{BASE_URL}/api/v1/subscriber/payments",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    params={
        "page": 1,
        "per_page": 20,
    },
)

data = response.json()
print(data)
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscriber/payments"

	q := url.Values{}
	q.Set("page", "1")
	q.Set("per_page", "20")
	endpoint += "?" + q.Encode()

	req, _ := http.NewRequest("GET", endpoint, nil)
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .get(format!("{BASE_URL}/api/v1/subscriber/payments"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .query(&[
            ("page", "1"),
            ("per_page", "20"),
        ])
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Subscriber Payment Details ​

Get one of the subscriber's payments.

PropertyValue
EndpointSubscriber Payment Details
MethodGET
URL/api/v1/subscriber/payments/{id}
AuthenticationBearer Token (Subscriber)

Request Headers:

HeaderValueRequired
Acceptapplication/jsonYes
AuthorizationBearer subscriber-tokenYes

Path Parameters:

ParameterTypeRequiredDescription
idintegerYesPayment ID

Request Body: None

Success Response (200 OK):

json
{
    "status": "success",
    "data": {
        "id": 881,
        "transaction_id": "a3f9c1d27b8e4_5c21ab",
        "amount": 550,
        "method": 11,
        "method_label": "Bkash",
        "reverted": false,
        "withdrawal": false,
        "note": null,
        "paid_at": "2026-10-02T10:12:00+06:00"
    }
}

Error Response (404 Not Found):

json
{
    "status": "error",
    "message": "Not Found"
}

Code Examples:

bash
curl -X GET "https://your-domain.com/api/v1/subscriber/payments/1" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer your-auth-token"
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$paymentId = 1;

$response = $client->request('GET', "/api/v1/subscriber/payments/{$paymentId}", [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const paymentId = 1;

const response = await fetch(`${BASE_URL}/api/v1/subscriber/payments/${paymentId}`, {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

payment_id = 1

response = requests.get(
    f"{BASE_URL}/api/v1/subscriber/payments/{payment_id}",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
)

data = response.json()
print(data)
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"strconv"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	paymentId := 1
	endpoint := baseURL + "/api/v1/subscriber/payments/" + strconv.Itoa(paymentId)

	req, _ := http.NewRequest("GET", endpoint, nil)
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();
    let payment_id = 1;

    let response = client
        .get(format!("{BASE_URL}/api/v1/subscriber/payments/{payment_id}"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

Subscriber Ledger ​

List the subscriber's wallet ledger lines, newest first.

PropertyValue
EndpointSubscriber Ledger
MethodGET
URL/api/v1/subscriber/ledger
AuthenticationBearer Token (Subscriber)

Request Headers:

HeaderValueRequired
Acceptapplication/jsonYes
AuthorizationBearer subscriber-tokenYes

Query Parameters:

ParameterTypeRequiredDescription
pageintegerNoPage number (default 1)
per_pageintegerNoItems per page, 1 to 50 (default 20)

Request Body: None

Success Response (200 OK):

json
{
    "status": "success",
    "data": [
        {
            "id": 99120,
            "transaction_id": "a3f9c1d27b8e4",
            "type": "deducted",
            "amount": -1000,
            "balance": 350,
            "note": "Package activation: Home Fiber 40",
            "invoice_id": 2041,
            "payment_id": null,
            "created_at": "2026-10-02T10:12:00+06:00"
        },
        {
            "id": 99104,
            "transaction_id": "e81c07fa52d93",
            "type": "topup",
            "amount": 1350,
            "balance": 1350,
            "note": null,
            "invoice_id": null,
            "payment_id": 879,
            "created_at": "2026-10-02T10:05:00+06:00"
        }
    ],
    "meta": {
        "current_page": 1,
        "last_page": 4,
        "per_page": 20,
        "total": 63
    }
}

Field notes:

  • type is one of:
    • topup: money added to the wallet.
    • deducted: money taken from the wallet (negative amount).
    • invoice_paid: an invoice paid by cash, cheque or similar; linked to both the invoice and the payment, and the balance does not change.
    • withdraw: a withdrawal.
    • invoice: an invoice line.
    • profit: a profit line.
    • other: any other ledger type.
  • balance is the wallet balance after this line.
  • invoice_id and payment_id link the line to an invoice or payment, or are null.

Error Response (401 Unauthorized):

json
{
    "message": "Unauthenticated."
}

Code Examples:

bash
curl -X GET "https://your-domain.com/api/v1/subscriber/ledger?page=1&per_page=20" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer your-auth-token"
php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://your-domain.com']);

$response = $client->request('GET', '/api/v1/subscriber/ledger', [
    'headers' => [
        'Accept'        => 'application/json',
        'Authorization' => 'Bearer your-auth-token',
    ],
    'query' => [
        'page'     => 1,
        'per_page' => 20,
    ],
]);

$data = json_decode($response->getBody(), true);
print_r($data);
javascript
const BASE_URL = 'https://your-domain.com';
const TOKEN = 'your-auth-token';

const params = new URLSearchParams({
  page: 1,
  per_page: 20,
});

const response = await fetch(`${BASE_URL}/api/v1/subscriber/ledger?${params}`, {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: `Bearer ${TOKEN}`,
  },
});

const data = await response.json();
console.log(data);
python
import requests

BASE_URL = "https://your-domain.com"
TOKEN = "your-auth-token"

response = requests.get(
    f"{BASE_URL}/api/v1/subscriber/ledger",
    headers={
        "Accept": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    },
    params={
        "page": 1,
        "per_page": 20,
    },
)

data = response.json()
print(data)
go
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
)

const baseURL = "https://your-domain.com"
const token = "your-auth-token"

func main() {
	endpoint := baseURL + "/api/v1/subscriber/ledger"

	q := url.Values{}
	q.Set("page", "1")
	q.Set("per_page", "20")
	endpoint += "?" + q.Encode()

	req, _ := http.NewRequest("GET", endpoint, nil)
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(body))
}
rust
use reqwest::Client;

const BASE_URL: &str = "https://your-domain.com";
const TOKEN: &str = "your-auth-token";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();

    let response = client
        .get(format!("{BASE_URL}/api/v1/subscriber/ledger"))
        .header("Accept", "application/json")
        .bearer_auth(TOKEN)
        .query(&[
            ("page", "1"),
            ("per_page", "20"),
        ])
        .send()
        .await?;

    let data: serde_json::Value = response.json().await?;
    println!("{data:#}");
    Ok(())
}

www.onezeroart.com