Documentacao do cardisk

Esta documentacao foi organizada para web com base no pacote publicado no PyPI (cardisk 0.4.7, publicado em 4 de marco de 2026).

Introducao

cardisk e um framework Python para construir aplicacoes USSD, com API baseada em decoradores e fluxo de menu interativo.

  • Simple API - Decorator-based routing for clean screen handlers
  • Menu System - Built-in support for interactive menus with automatic navigation
  • Session Management - Automatic session handling with in-memory or Redis storage
  • Monitoring - Built-in Prometheus metrics endpoint
  • Error Handling - Robust error handling middleware
  • Type Safe - Full type hints support
  • Fast - High-performance runtime with Uvicorn

Instalacao

Criar e ativar ambiente virtual

Antes de instalar o cardisk, crie um ambiente virtual para este projeto e evite conflitos de bibliotecas.

python -m venv .venv

Ative o ambiente virtual:

# Mac/Linux
source .venv/bin/activate
# alternativa
. .venv/bin/activate
# Windows
.venv\Scripts\activate

Instalacao de producao

pip install cardisk

Quick Start

Crie um ficheiro app.py:

from cardisk import Cardisk, ussd

app = Cardisk()

@app.route("/")
def main_menu():
    ussd.menu("Welcome to Wolke Services", [
        ("Loans", "/loans"),
        ("Savings", "/savings"),
        ("Insurance", "/insurance")
    ])

@app.route("/loans")
def loans():
    ussd.menu("Loans Menu", [
        ("Apply for loan", "/loan/apply"),
        ("Check loan status", "/loan/status"),
        ("Repay loan", "/loan/repay")
    ])

@app.route("/loan/apply")
def loan_apply():
    ussd.screen(f"Enter loan amount for {ussd.msisdn}")
    ussd.next("/loan/confirm")

@app.route("/loan/confirm")
def loan_confirm():
    amount = ussd.input
    ussd.screen(f"Loan of ${amount} submitted successfully for {ussd.msisdn}")
    ussd.end()

Execute a aplicacao:

cardisk runserver

Ou com Uvicorn:

uvicorn app:app.app --reload --port 8000

API

Setup da aplicacao

from cardisk import Cardisk, ussd

app = Cardisk()

Decorador de rota: @app.route()

@app.route("/path")
def handler():
    pass
  • As rotas devem iniciar com /.
  • Use / como ponto de entrada do menu principal.

Objeto ussd

Propriedades:

  • ussd.msisdn: numero do utilizador
  • ussd.session: ID da sessao atual
  • ussd.input: entrada do utilizador no passo anterior

Metodos principais:

ussd.menu("Main Menu", [
    ("Option 1", "/route1"),
    ("Option 2", "/route2")
])

ussd.screen("Hello!")
ussd.next("/verify-pin")
ussd.end()

Protocolo XML USSD

Formato da requisicao

<ussd>
    <type>1</type>
    <msisdn>254712345678</msisdn>
    <sessionid>unique-session-id</sessionid>
    <msg>user-input</msg>
</ussd>

Formato da resposta

<ussd>
    <type>2</type>
    <msg>Response text</msg>
</ussd>

Testes

Cardisk Simulator

After running your cardisk app with cardisk runserver, open your browser and visit http://0.0.0.0:8000 or http://127.0.0.1:8000 to access the cardisk simulator.

This is the interface of the Cardisk Simulator running.
cardisk simulator
Make sure the endpoint URL matches the URL you opened (http://0.0.0.0:8000 or http://127.0.0.1:8000), then click Dial.
cardisk simulator
This is the Cardisk Simulator in action, you can use the phone to send requests to the application
cardisk simulator
You can check on the right-side of the screen logs for both requests and responses in XML.
cardisk simulator
On the left-bottom-side you can find information about the current session, whether is's active or not.
cardisk simulator
On the section highlighted bellow, you can dial to close the current session and start a new one, ar you can just reset the session.
cardisk simulator
And here, you can manage the information sent when you dial.
cardisk simulator

Com cURL

1. Iniciar nova sessao:

curl -X POST http://localhost:8000/ \
  -H "Content-Type: application/xml" \
  -d '<ussd><type>1</type><msisdn>254712345678</msisdn><sessionid>test123</sessionid><msg></msg></ussd>'

2. Selecionar opcao de menu (ex.: opcao 1):

curl -X POST http://localhost:8000/ \
  -H "Content-Type: application/xml" \
  -d '<ussd><type>2</type><msisdn>254712345678</msisdn><sessionid>test123</sessionid><msg>1</msg></ussd>'

3. Enviar um input:

curl -X POST http://localhost:8000/ \
  -H "Content-Type: application/xml" \
  -d '<ussd><type>2</type><msisdn>254712345678</msisdn><sessionid>test123</sessionid><msg>500</msg></ussd>'

Com Python

import httpx

client = httpx.Client(base_url="http://localhost:8000")

# Start session
response = client.post("/", content="""
<ussd>
    <type>1</type>
    <msisdn>254712345678</msisdn>
    <sessionid>test123</sessionid>
    <msg></msg>
</ussd>
""", headers={"Content-Type": "application/xml"})

print(response.text)

# Continue session
response = client.post("/", content="""
<ussd>
    <type>2</type>
    <msisdn>254712345678</msisdn>
    <sessionid>test123</sessionid>
    <msg>1</msg>
</ussd>
""", headers={"Content-Type": "application/xml"})

print(response.text)

CLI

Criar novo projeto

cardisk new myproject

Acessa a pasta do projecto

cd myproject

Executar servidor

cardisk runserver --host 0.0.0.0 --port 8000

Uso avancado

Tratamento de erro personalizado

@app.route("/transfer")
def transfer():
    try:
        amount = float(ussd.input)
        if amount <= 0:
            ussd.screen("Invalid amount. Please try again.")
            ussd.next("/transfer")
        else:
            ussd.screen(f"Transfer of ${amount} successful!")
            ussd.end()
    except ValueError:
        ussd.screen("Invalid input. Please enter a number.")
        ussd.next("/transfer")

Formulario multi-step

@app.route("/register")
def register_name():
    ussd.screen("Enter your name:")
    ussd.next("/register/age")

@app.route("/register/age")
def register_age():
    name = ussd.input
    ussd.screen(f"Hello {name}! Enter your age:")
    ussd.next("/register/confirm")

@app.route("/register/confirm")
def register_confirm():
    age = ussd.input
    ussd.screen(f"Registration complete! Age: {age}")
    ussd.end()