Intertext provides a RESTful API that allows you to integrate Intertext’s services into your own applications, scripts, and workflows. It is NOT intended to be an api you can build public services from. The API is rate limited so you can only send a few commands per minute, but enough to feel interactive and responsive.

It is intended to be used in fun and/or useful applications, like bringing a TRS-80, Commodore PET or a PiDP-11 to the Internet. By using a serial connection to a Raspberry Pi running a small gateway software, you can build software to explore how it would have been if the Internet was available in 1977, or use it like an advanced BBS. You could use it to build a great Pebble Time application.

There is no in-between user messaging or any forums where you can interact with other users. It would have been fun, but then we would have to monitor it and log the messaging in case of misuse. “Misusers” are why we can’t have nice things. Be good.

The AI is limited to one question - one answer, so no AI chat history. The answers are quite short so there is not room for getting complete instuctions on how to build an interstellar rocketship.

It’s possible for a teacher to sign up and then register a token to hand out in a class API programming excercises. Afterwards the teacher can revoke the API key. The students may also set up their own accounts if they want to continue after the lessons ended.

Table of Contents

  1. Overview
  2. Getting Started
  3. Authentication
  4. API Endpoints
  5. Request & Response Format
  6. Error Handling
  7. Rate Limits
  8. Code Examples
  9. Best Practices

Overview

What is the Intertext API?

The Intertext API allows programmatic access to all Intertext services without using Signal messaging. Perfect for:

  • Web applications: Integrate weather, time, or news into your website
  • Mobile apps: Build native apps powered by Intertext services
  • IoT devices: Connect smart home devices to Intertext
  • Automation scripts: Automate tasks with Intertext’s intelligence
  • Dashboard integrations: Display Intertext data in your business dashboards

Why Use the API?

  • Programmatic access: No Signal messaging required
  • Real-time responses: Instant HTTP responses (no polling)
  • Flexible integration: Use any programming language with HTTP support
  • Same features: Access all services available via Signal
  • Token-based auth: Secure API key authentication

Prerequisites

  • Active Intertext account (register via Signal: +46737609889)
  • API access enabled on your account (Pro plan required for API access)
  • API token generated via Signal

Getting Started

1. Enable API Access

API access requires a Pro plan subscription.

Check your current plan:

You: settings
Intertext: Account Plan: Pro
     API Access: Enabled ✓

Upgrade if needed: Contact support@yourdomain.com to upgrade to Pro plan.

2. Generate API Token

Use Signal to generate your API token:

You: create api token
Intertext: API Token created successfully!

     Name: My API Token
     Token: hal_sk_abc123def456ghi789jkl012mno345pqr678stu901

     Keep this token secret! It grants full access to your account.

     Use in API requests:
     Authorization: Bearer hal_sk_abc123...

You: create api token "Production App"
Intertext: API Token created successfully!

     Name: Production App
     Token: hal_sk_xyz...

Token naming: Give your tokens descriptive names to track usage:

  • “Production App”
  • “Development”
  • “Mobile App”
  • “Personal Scripts”

3. List Your Tokens

View all active API tokens:

You: list api tokens
Intertext: Your API Tokens:

     1. Production App
        Created: Jan 1, 2026
        Last used: 2 hours ago

     2. Development
        Created: Dec 15, 2025
        Last used: Never

4. Revoke a Token

Delete tokens you no longer need:

You: revoke api token "Development"
Intertext: API Token "Development" has been revoked.
     It can no longer be used for API access.

Authentication

API Token

All API requests require authentication using your API token.

Header format:

Authorization: Bearer hal_sk_abc123def456ghi789jkl012mno345pqr678stu901

Example request:

curl -H "Authorization: Bearer hal_sk_abc123..." \
     https://api.hal.yourdomain.com/v1/weather?location=Stockholm

Base URL

Production: https://api.hal.yourdomain.com/v1
Staging:    https://staging-api.hal.yourdomain.com/v1

For self-hosted deployments:

http://your-server-ip:20001/api/v1

API Endpoints

Weather

Get current weather conditions.

Endpoint: GET /v1/weather

Parameters:

  • location (required) - City name or “lat:X,lon:Y”
  • units (optional) - “metric” or “imperial” (default: your account setting)

Example:

curl -H "Authorization: Bearer YOUR_TOKEN" \
     "https://api.hal.yourdomain.com/v1/weather?location=Stockholm"

Response:

{
  "status": "success",
  "data": {
    "location": {
      "city": "Stockholm",
      "country": "Sweden",
      "coordinates": {
        "lat": 59.33,
        "lon": 18.07
      }
    },
    "current": {
      "temperature": 5,
      "feels_like": 2,
      "conditions": "Partly cloudy",
      "humidity": 78,
      "wind_speed": 12,
      "wind_direction": "NW"
    },
    "units": "metric",
    "timestamp": "2026-01-03T14:30:00Z"
  }
}

Time

Get current time for a location or timezone.

Endpoint: GET /v1/time

Parameters:

  • location (optional) - City name or timezone (default: your account setting)

Example:

curl -H "Authorization: Bearer YOUR_TOKEN" \
     "https://api.hal.yourdomain.com/v1/time?location=Tokyo"

Response:

{
  "status": "success",
  "data": {
    "location": "Tokyo, Japan",
    "timezone": "Asia/Tokyo",
    "datetime": "2026-01-03T23:30:00+09:00",
    "date": "2026-01-03",
    "time": "23:30:00",
    "day_of_week": "Friday",
    "unix_timestamp": 1735916400
  }
}

News

Get latest news headlines.

Endpoint: GET /v1/news

Parameters:

  • category (optional) - News category (default: “general”)
  • limit (optional) - Number of articles (default: 5, max: 20)

Categories: general, technology, business, sports, entertainment

Example:

curl -H "Authorization: Bearer YOUR_TOKEN" \
     "https://api.hal.yourdomain.com/v1/news?category=technology&limit=3"

Response:

{
  "status": "success",
  "data": {
    "category": "technology",
    "articles": [
      {
        "title": "New AI breakthrough announced",
        "summary": "Researchers unveil significant advancement...",
        "published_at": "2026-01-03T12:00:00Z",
        "source": "BBC News"
      },
      {
        "title": "Tech company launches new product",
        "summary": "Industry leader releases innovative...",
        "published_at": "2026-01-03T10:30:00Z",
        "source": "BBC News"
      }
    ],
    "count": 2
  }
}

Pollen Forecast (Base/Pro Plans)

Get pollen and air quality information.

Endpoint: GET /v1/pollen

Parameters:

  • location (required) - City name or coordinates

Example:

curl -H "Authorization: Bearer YOUR_TOKEN" \
     "https://api.hal.yourdomain.com/v1/pollen?location=Stockholm"

Response:

{
  "status": "success",
  "data": {
    "location": "Stockholm, Sweden",
    "pollen": {
      "level": "medium",
      "dominant_types": ["birch", "grass"],
      "birch": 3,
      "grass": 2,
      "ragweed": 0
    },
    "air_quality": {
      "index": 42,
      "category": "good",
      "pm25": 8,
      "pm10": 15
    },
    "timestamp": "2026-01-03T14:30:00Z"
  }
}

Get directions between two points.

Endpoint: GET /v1/navigate

Parameters:

  • from (required) - Starting location
  • to (required) - Destination
  • mode (optional) - “driving”, “walking”, “cycling” (default: “driving”)

Example:

curl -H "Authorization: Bearer YOUR_TOKEN" \
     "https://api.hal.yourdomain.com/v1/navigate?from=Stockholm&to=Uppsala&mode=driving"

Response:

{
  "status": "success",
  "data": {
    "from": {
      "name": "Stockholm, Sweden",
      "coordinates": {"lat": 59.33, "lon": 18.07}
    },
    "to": {
      "name": "Uppsala, Sweden",
      "coordinates": {"lat": 59.86, "lon": 17.64}
    },
    "route": {
      "distance": 71.2,
      "duration": 3600,
      "mode": "driving"
    },
    "maps_url": "https://www.google.com/maps/dir/?api=1&origin=59.33,18.07&destination=59.86,17.64"
  }
}

Nearby Places (Pro Plan)

Find nearby points of interest.

Endpoint: GET /v1/nearby

Parameters:

  • location (required) - City, address, or coordinates
  • type (required) - Place type (restaurant, atm, cafe, etc.)
  • radius (optional) - Search radius in km (default: 1, max: 5)
  • limit (optional) - Number of results (default: 5, max: 20)

Example:

curl -H "Authorization: Bearer YOUR_TOKEN" \
     "https://api.hal.yourdomain.com/v1/nearby?location=Stockholm&type=restaurant&radius=2"

Response:

{
  "status": "success",
  "data": {
    "query": {
      "location": "Stockholm, Sweden",
      "type": "restaurant",
      "radius": 2
    },
    "places": [
      {
        "name": "Restaurant ABC",
        "distance": 0.3,
        "address": "123 Main Street",
        "coordinates": {"lat": 59.33, "lon": 18.07}
      },
      {
        "name": "Bistro XYZ",
        "distance": 0.5,
        "address": "456 Oak Avenue",
        "coordinates": {"lat": 59.34, "lon": 18.08}
      }
    ],
    "count": 2
  }
}

Account Information

Get your account details.

Endpoint: GET /v1/account

Example:

curl -H "Authorization: Bearer YOUR_TOKEN" \
     https://api.hal.yourdomain.com/v1/account

Response:

{
  "status": "success",
  "data": {
    "phone": "+46737609889",
    "plan": "pro",
    "locale": "en-US",
    "units": "metric",
    "created_at": "2025-12-01T10:00:00Z",
    "api_enabled": true
  }
}

Request & Response Format

Request Headers

Required:

Authorization: Bearer YOUR_API_TOKEN

Optional:

Content-Type: application/json
Accept: application/json

Response Format

All responses use JSON format with this structure:

Success:

{
  "status": "success",
  "data": { /* endpoint-specific data */ }
}

Error:

{
  "status": "error",
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message"
  }
}

HTTP Status Codes

Code Meaning Description
200 OK Request successful
400 Bad Request Invalid parameters
401 Unauthorized Missing or invalid API token
403 Forbidden Feature not available on your plan
404 Not Found Resource not found
429 Too Many Requests Rate limit exceeded
500 Internal Server Error Server error (contact support)

Error Handling

Common Error Codes

Authentication Errors:

{
  "status": "error",
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or missing API token"
  }
}

Plan Restriction:

{
  "status": "error",
  "error": {
    "code": "PLAN_REQUIRED",
    "message": "This feature requires Pro plan"
  }
}

Invalid Parameters:

{
  "status": "error",
  "error": {
    "code": "INVALID_PARAMETER",
    "message": "Location parameter is required"
  }
}

Rate Limit:

{
  "status": "error",
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Retry after 60 seconds."
  }
}

Resource Not Found:

{
  "status": "error",
  "error": {
    "code": "NOT_FOUND",
    "message": "Location 'Atlantis' not found"
  }
}

Rate Limits

Default Limits

Plan Requests per Hour Burst Limit
Free N/A (API not available) N/A
Base N/A (API not available) N/A
Pro 1,000 100/minute
Enterprise Custom Custom

Rate Limit Headers

Every response includes rate limit information:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 987
X-RateLimit-Reset: 1735920000

Handling Rate Limits

When you exceed the rate limit:

Response:

HTTP/1.1 429 Too Many Requests
Retry-After: 60
{
  "status": "error",
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Retry after 60 seconds."
  }
}

Best practices:

  • Implement exponential backoff
  • Cache responses when possible
  • Monitor rate limit headers
  • Spread requests over time

Code Examples

cURL

Weather request:

curl -X GET \
  -H "Authorization: Bearer hal_sk_abc123..." \
  "https://api.hal.yourdomain.com/v1/weather?location=Stockholm"

Python

Using requests library:

import requests

API_TOKEN = "hal_sk_abc123..."
BASE_URL = "https://api.hal.yourdomain.com/v1"

headers = {
    "Authorization": f"Bearer {API_TOKEN}"
}

# Get weather
response = requests.get(
    f"{BASE_URL}/weather",
    headers=headers,
    params={"location": "Stockholm"}
)

if response.status_code == 200:
    data = response.json()
    print(f"Temperature: {data['data']['current']['temperature']}°C")
else:
    print(f"Error: {response.json()['error']['message']}")

# Get news
response = requests.get(
    f"{BASE_URL}/news",
    headers=headers,
    params={"category": "technology", "limit": 5}
)

news = response.json()
for article in news['data']['articles']:
    print(f"- {article['title']}")

JavaScript (Node.js)

Using fetch:

const API_TOKEN = 'hal_sk_abc123...';
const BASE_URL = 'https://api.hal.yourdomain.com/v1';

async function getWeather(location) {
  const response = await fetch(
    `${BASE_URL}/weather?location=${encodeURIComponent(location)}`,
    {
      headers: {
        'Authorization': `Bearer ${API_TOKEN}`
      }
    }
  );

  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.error.message);
  }

  return await response.json();
}

async function main() {
  try {
    const weather = await getWeather('Stockholm');
    console.log(`Temperature: ${weather.data.current.temperature}°C`);
  } catch (error) {
    console.error('Error:', error.message);
  }
}

main();

JavaScript (Browser)

Fetch API:

const API_TOKEN = 'hal_sk_abc123...';

async function displayWeather() {
  const location = document.getElementById('location').value;

  try {
    const response = await fetch(
      `https://api.hal.yourdomain.com/v1/weather?location=${location}`,
      {
        headers: {
          'Authorization': `Bearer ${API_TOKEN}`
        }
      }
    );

    const data = await response.json();

    if (data.status === 'success') {
      document.getElementById('result').innerHTML = `
        <h3>${data.data.location.city}</h3>
        <p>Temperature: ${data.data.current.temperature}°C</p>
        <p>Conditions: ${data.data.current.conditions}</p>
      `;
    } else {
      alert(data.error.message);
    }
  } catch (error) {
    console.error('Error:', error);
  }
}

PHP

Using cURL:

<?php
$api_token = 'hal_sk_abc123...';
$base_url = 'https://api.hal.yourdomain.com/v1';

function getWeather($location) {
    global $api_token, $base_url;

    $url = $base_url . '/weather?location=' . urlencode($location);

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: Bearer ' . $api_token
    ]);

    $response = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $data = json_decode($response, true);

    if ($http_code === 200) {
        return $data['data'];
    } else {
        throw new Exception($data['error']['message']);
    }
}

try {
    $weather = getWeather('Stockholm');
    echo "Temperature: " . $weather['current']['temperature'] . "°C\n";
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}
?>

Ruby

Using net/http:

require 'net/http'
require 'json'
require 'uri'

API_TOKEN = 'hal_sk_abc123...'
BASE_URL = 'https://api.hal.yourdomain.com/v1'

def get_weather(location)
  uri = URI("#{BASE_URL}/weather?location=#{URI.encode_www_form_component(location)}")

  request = Net::HTTP::Get.new(uri)
  request['Authorization'] = "Bearer #{API_TOKEN}"

  response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
    http.request(request)
  end

  data = JSON.parse(response.body)

  if response.code == '200'
    data['data']
  else
    raise data['error']['message']
  end
end

begin
  weather = get_weather('Stockholm')
  puts "Temperature: #{weather['current']['temperature']}°C"
rescue => e
  puts "Error: #{e.message}"
end

Best Practices

Security

  1. Keep tokens secret:
    • Never commit tokens to version control
    • Use environment variables or secret managers
    • Rotate tokens regularly
  2. Use HTTPS:
    • Always use HTTPS endpoints
    • Verify SSL certificates
  3. Token per application:
    • Create separate tokens for each app/environment
    • Name tokens descriptively
    • Revoke unused tokens

Performance

  1. Cache responses:
    • Cache weather data for 10-30 minutes
    • Cache news for 10-15 minutes
    • Cache time data for 1 minute
  2. Implement retries:
    • Use exponential backoff
    • Retry on 429, 500, 503 errors
    • Don’t retry on 400, 401, 403 errors
  3. Monitor rate limits:
    • Track X-RateLimit-Remaining header
    • Slow down when approaching limit
    • Implement request queuing

Error Handling

  1. Check HTTP status codes:
    • Don’t assume 200 OK
    • Handle all error codes appropriately
  2. Parse error messages:
    • Display helpful messages to users
    • Log detailed errors for debugging
  3. Implement fallbacks:
    • Graceful degradation when API is unavailable
    • Cached data as fallback

Example: Production-Ready Request

import requests
import time
from functools import wraps

API_TOKEN = os.getenv('INTERTEXT_API_TOKEN')
BASE_URL = 'https://api.hal.yourdomain.com/v1'
CACHE = {}

def retry_with_backoff(max_retries=3):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except requests.exceptions.RequestException as e:
                    if attempt == max_retries - 1:
                        raise
                    wait = 2 ** attempt
                    time.sleep(wait)
        return wrapper
    return decorator

@retry_with_backoff()
def api_request(endpoint, params=None):
    cache_key = f"{endpoint}:{str(params)}"

    # Check cache
    if cache_key in CACHE:
        cached_data, timestamp = CACHE[cache_key]
        if time.time() - timestamp < 600:  # 10 min TTL
            return cached_data

    # Make request
    response = requests.get(
        f"{BASE_URL}/{endpoint}",
        headers={'Authorization': f'Bearer {API_TOKEN}'},
        params=params,
        timeout=10
    )

    # Check rate limit
    remaining = int(response.headers.get('X-RateLimit-Remaining', 999))
    if remaining < 10:
        print(f"Warning: Only {remaining} requests remaining")

    # Handle errors
    if response.status_code == 429:
        retry_after = int(response.headers.get('Retry-After', 60))
        raise Exception(f"Rate limited. Retry after {retry_after}s")

    response.raise_for_status()
    data = response.json()

    if data['status'] != 'success':
        raise Exception(data['error']['message'])

    # Cache result
    CACHE[cache_key] = (data['data'], time.time())

    return data['data']

Support

Getting Help

  • Documentation: This page
  • Email support: api-support@yourdomain.com
  • Status page: status.hal.yourdomain.com
  • Signal: +46737609889

Reporting Issues

When reporting API issues, include:

  • Your account phone number (last 4 digits only)
  • API endpoint and parameters
  • Request timestamp
  • Error message received
  • Expected vs actual behavior

Feature Requests

Have an idea for a new API endpoint or feature?

  • Email: api-feedback@yourdomain.com
  • GitHub: github.com/yourorg/hal_system/issues

Back to Home View Features Privacy Policy