Go to file
2026-02-06 00:51:48 +05:00
2026-02-06 00:38:02 +05:00
2026-02-06 00:49:38 +05:00
2026-02-06 00:38:02 +05:00
2026-02-06 00:49:38 +05:00
2026-02-06 00:49:38 +05:00
2026-02-06 00:38:02 +05:00
2026-02-06 00:38:02 +05:00
2026-02-06 00:38:02 +05:00
2026-02-06 00:38:02 +05:00
2026-02-06 00:38:02 +05:00
2026-02-06 00:51:48 +05:00
2026-02-06 00:38:02 +05:00

Textpipe - SMS API Gateway

An Android app that turns your phone into an SMS API gateway with a web interface.

Features

  • REST API - Send and receive SMS via HTTP endpoints
  • Dual SIM Support - Each SIM gets its own API key
  • Web UI - Google Messages-like interface accessible from any browser
  • Local Database - All messages stored locally with delivery tracking
  • Background Service - Runs as a foreground service with persistent notification
  • Auto-start - Optionally start on device boot
  • Root Port Redirect - Use ports 80/443 with root access via iptables

Requirements

  • Android 7.0+ (API 24+)
  • SMS permissions
  • Phone state permissions (for dual SIM)
  • (Optional) Root access for privileged ports

Building

Prerequisites

  • Android Studio or command line with Android SDK
  • JDK 11+
  • Node.js 18+ (for web UI)

Build Steps

  1. Clone the repository

    git clone <repo-url>
    cd textpipe
    
  2. Build the Web UI

    cd webui
    npm install
    npm run build
    cd ..
    

    This builds the Vue frontend to app/src/main/assets/webui/

  3. Build the Android App

    ./gradlew assembleDebug
    

    The APK will be at app/build/outputs/apk/debug/app-debug.apk

  4. Install on device

    adb install app/build/outputs/apk/debug/app-debug.apk
    

Release Build

./gradlew assembleRelease

Note: You'll need to configure signing in app/build.gradle.kts for release builds.

Usage

Initial Setup

  1. Install and open the app
  2. Grant all requested permissions (SMS, Phone, Notifications)
  3. Note the API key(s) shown for each SIM card
  4. Configure the port (default: 8080)
  5. Tap "Start Server"
  6. (Optional) Disable battery optimization for reliable background operation

API Endpoints

Base URL: http://<phone-ip>:<port>

Status (No auth required)

GET /api/status

Returns server status and SIM information.

Send SMS

POST /api/sms/send
Header: X-API-Key: <your-api-key>
Content-Type: application/json

{
  "to": "+1234567890",
  "text": "Hello from Textpipe!"
}

Response:

{
  "id": 1,
  "status": "pending",
  "simSlot": 0
}

List Messages

GET /api/sms/messages
Header: X-API-Key: <your-api-key>

Optional query parameter: ?type=sent or ?type=received

Response:

{
  "messages": [
    {
      "id": 1,
      "type": "sent",
      "address": "+1234567890",
      "text": "Hello!",
      "simSlot": 0,
      "status": "delivered",
      "timestamp": 1707148800000,
      "deliveryTimestamp": 1707148805000
    }
  ],
  "total": 1
}

Get Message Status

GET /api/sms/status/{id}
Header: X-API-Key: <your-api-key>

Authentication

Pass your API key in one of these ways:

  • Header: Authorization: Bearer <key>
  • Header: X-API-Key: <key>
  • Query param: ?api_key=<key>

Each SIM card has its own unique API key. The API key determines which SIM sends the message.

Web Interface

Open http://<phone-ip>:<port>/ in any browser to access the web UI.

  1. Enter your API key to login
  2. View conversations grouped by contact
  3. Send new messages using the + button
  4. Click on a conversation to view message thread

cURL Examples

Send SMS:

curl -X POST http://10.0.1.12:8080/api/sms/send \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key-here" \
  -d '{"to": "+1234567890", "text": "Hello!"}'

Check status:

curl http://10.0.1.12:8080/api/status

List messages:

curl -H "X-API-Key: your-api-key-here" \
  http://10.0.1.12:8080/api/sms/messages

Get specific message:

curl -H "X-API-Key: your-api-key-here" \
  http://10.0.1.12:8080/api/sms/status/1

Configuration

Port Configuration

  • Default port: 8080
  • Can be changed in the app UI
  • For ports below 1024 (like 80 or 443), root access is required
  • With root, the app uses iptables to redirect traffic from the privileged port to the actual server port

Auto-start

Enable "Auto-start on boot" in Settings to automatically start the server when the device boots.

Battery Optimization

For reliable background operation, disable battery optimization for Textpipe:

  1. Go to Settings in the app
  2. Tap "Disable" next to Battery Optimization
  3. Confirm in the system dialog

Project Structure

textpipe/
├── app/                          # Android app
│   └── src/main/
│       ├── java/sh/sar/textpipe/
│       │   ├── MainActivity.kt
│       │   ├── TextpipeApplication.kt
│       │   ├── data/
│       │   │   ├── db/           # Room database
│       │   │   ├── model/        # API models
│       │   │   └── repository/   # Data repository
│       │   ├── server/           # Ktor HTTP server
│       │   │   ├── TextpipeServer.kt
│       │   │   ├── auth/         # API key auth
│       │   │   └── routes/       # API endpoints
│       │   ├── service/          # Android services
│       │   │   ├── TextpipeService.kt
│       │   │   ├── SmsSender.kt
│       │   │   ├── SmsReceiver.kt
│       │   │   └── BootReceiver.kt
│       │   ├── sim/              # SIM management
│       │   ├── root/             # Root utilities
│       │   └── ui/               # Compose UI
│       ├── assets/webui/         # Built web UI
│       └── AndroidManifest.xml
├── webui/                        # Vue.js web interface
│   ├── src/
│   │   ├── App.vue
│   │   ├── api.js
│   │   ├── style.css
│   │   └── components/
│   ├── package.json
│   └── vite.config.js
├── gradle/
│   └── libs.versions.toml        # Dependency versions
└── build.gradle.kts

Tech Stack

Android App

  • Kotlin
  • Jetpack Compose (UI)
  • Ktor CIO (HTTP server)
  • Room (Database)
  • Kotlin Coroutines
  • kotlinx.serialization (JSON)

Web UI

  • Vue 3
  • Vite
  • Vanilla CSS

Message Status Flow

pending → sent → delivered
              ↘ failed
  • pending - Message queued, sending in progress
  • sent - Message sent successfully
  • delivered - Delivery confirmation received
  • failed - Send failed

Troubleshooting

"Address already in use" error

The port is still bound from a previous instance. Either:

  • Wait a few seconds and try again
  • Change to a different port
  • Force stop the app and restart

Server doesn't start

  • Check that no other app is using the port
  • Verify all permissions are granted
  • Check logcat for errors: adb logcat -s TextpipeServer TextpipeService

Messages not sending

  • Verify SMS permission is granted
  • Check you have cellular signal
  • Ensure the API key matches an active SIM

Web UI not loading

  • Verify the server is running (check app status)
  • Check you're using the correct IP and port
  • Try accessing /api/status directly

License

MIT

Description
Simple SMS API Server with WebUI for bulk SMS with Dual SIM support
Readme 264 KiB
Languages
Kotlin 82%
HTML 18%