β˜• PhoneTea

πŸ“‘ PhoneTea Developer API Documentation

Version: 1.2.0
Last Updated: March 29, 2026

Welcome to the PhoneTea Developer API. This REST API provides programmatic access to our comprehensive phone number review database, spam detection system, and analytics platform.


πŸš€ Quick Start

Prerequisites

Before using the PhoneTea API, you need:

  1. A PhoneTea account - Sign up free
  2. A Premium subscription - API access requires Monthly ($9.99), Yearly ($99.99), or Lifetime ($499.99) Premium
  3. An API key - Create one from your Developer Dashboard after subscribing

Important: Free accounts do not have API access. Upgrade to Premium to get started with 500-2,500 free API calls per month.

Base URLs

Production: https://us-east1-{your-project-id}.cloudfunctions.net/api

Authentication

All API requests require a Bearer token in the Authorization header:

Authorization: Bearer YOUR_API_KEY

Your First Request

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://us-east1-{project-id}.cloudfunctions.net/api/v1/phone/lookup?number=5551234567"

πŸ”‘ Authentication

Getting Your API Key

For Premium Users:

  1. Subscribe to any Premium plan (Monthly, Yearly, or Lifetime)
  2. Navigate to Settings β†’ Developer β†’ API Keys
  3. Click Create API Key and choose a name and type
  4. Copy your key immediately β€” it will only be shown once

For API Subscription Users (Additional Capacity):

  1. Must have an active Premium subscription first
  2. Navigate to Settings β†’ Developer β†’ API Pricing
  3. Purchase an API subscription tier (Pay-As-You-Go, Starter, Professional, Business, or Enterprise)
  4. Your quota increases automatically (Premium + API tier combined)
  5. Enterprise and Custom tiers require business verification + admin approval (24-48 hours)

API Key Types

Type Purpose Rate Limit Best For
Production Live applications Based on subscription tier Production apps
Sandbox Testing & development 100/day Development & testing
Enterprise High-volume approved Custom limits Large integrations

API Key Lifecycle

Event What Happens
Subscribe to Premium API access granted β€” create your key manually
Purchase API Subscription Your quota increases (Premium + API tier combined)
Upgrade API Tier Key limit increased immediately
Downgrade API Tier Key limit reduced at end of billing period
Cancel API Subscription Key reverts to Premium-only quota
Cancel Premium All keys deactivated, API access revoked
Refund Premium Immediate deactivation of all keys

Using Your API Key

// Node.js Example
const headers = {
  'Authorization': `Bearer ${YOUR_API_KEY}`,
  'Content-Type': 'application/json'
};

fetch('https://api-endpoint/v1/phone/lookup?number=5551234567', { headers })
  .then(res => res.json())
  .then(data => console.log(data));

Security Best Practices

// ❌ DON'T: Hardcode keys in source code
const apiKey = 'pt_prod_1234567890abcdef';

// βœ… DO: Use environment variables
const apiKey = process.env.PHONETEA_API_KEY;

// ❌ DON'T: Expose keys in client-side JavaScript
// βœ… DO: Proxy requests through your backend server

πŸ“Š Rate Limits & Pricing

Premium Subscription API Quotas (Included Free)

Premium subscribers get free API calls each month as part of their subscription:

Premium Tier Monthly API Quota Subscription Price API Discount
Free 0 (No API access) $0 -
Monthly Pro 500 calls/month $9.99/mo 10% off API tiers
Yearly Pro 1,000 calls/month $99.99/yr 15% off API tiers
Lifetime Pro 2,500 calls/month $499.99 (one-time) 20% off API tiers

Note: Premium subscription is required for any API access. Free users cannot use the API.

API Subscription Tiers (Additional Capacity)

For higher volume needs, Premium users can purchase an additional API subscription:

API Tier Monthly Limit Price Cost per Call Approval
Pay-As-You-Go Unlimited $0/mo base $0.03/call Instant
Starter 5,000 calls/mo $29/mo $0.0058 Instant
Professional 20,000 calls/mo $79/mo $0.0040 Instant
Business 75,000 calls/mo $199/mo $0.0027 Instant
Enterprise 250,000 calls/mo $499/mo $0.0020 24-48 hours
Custom 250,000+ Contact Sales Volume rates Required

Understanding Your Total Quota

Your total monthly API limit = Premium quota + API subscription quota

Example:

Yearly Pro Premium:     1,000 calls/month (included free)
+ Starter API Tier:   + 5,000 calls/month
─────────────────────────────────────────
= Total Available:      6,000 calls/month

Consumption Order: Your included Premium calls are always consumed first. Once exhausted, calls draw from your purchased API subscription quota. For PAYG users, included calls are free β€” billing at $0.03/call starts only after included calls are used up.

Quota Reset Schedule

Your two quota pools reset independently:

Quota Type Resets On
Included (Premium) 1st of every month at 00:00 UTC
Purchased (API) Your Stripe billing date (subscription renewal)

Unused calls do not roll over to the next period.

Premium User Discounts

Premium subscribers receive discounts on API subscription tiers:

Premium Tier Base Discount Business Verified Bonus Max Discount
Monthly Pro 10% off +5% 15%
Yearly Pro 15% off +5% 20%
Lifetime Pro 20% off +5% 25%

Maximum combined discount capped at 30%

Example Pricing with Discount:

Professional Tier: $79/mo
Yearly Pro Discount: 15% off
─────────────────────────────
Your Price: $67.15/mo (save $11.85)

πŸ’³ Pay-As-You-Go Billing

Pay-As-You-Go (PAYG) is perfect for variable usage or testing before committing to a fixed tier.

How PAYG Works

PAYG Response Headers

PAYG requests include special billing headers:

X-Billing-Mode: pay_as_you_go
X-Usage-ThisMonth: 1547
X-Included-Quota: 1000
X-Included-Used: 1000
X-Billable-Calls: 547
X-Cost-Per-Request: 0.03
X-Estimated-Monthly-Cost: 16.4100
X-Usage-Reset: 1735689600
Header Description
X-Billing-Mode Always pay_as_you_go for PAYG keys
X-Usage-ThisMonth Total API calls this billing cycle
X-Included-Quota Your included Premium calls (free tier)
X-Included-Used Included calls consumed (not billed)
X-Billable-Calls Calls beyond included quota (billed at $0.03)
X-Cost-Per-Request Cost per billable API call ($0.03)
X-Estimated-Monthly-Cost Projected cost for billable calls only
X-Usage-Reset Unix timestamp when billing cycle resets

PAYG Example

curl -I -H "Authorization: Bearer YOUR_PAYG_API_KEY" \
  "https://us-east1-project.cloudfunctions.net/api/v1/phone/lookup?number=5551234567"

# Response Headers:
# X-Billing-Mode: pay_as_you_go
# X-Usage-ThisMonth: 1248
# X-Included-Quota: 1000
# X-Included-Used: 1000
# X-Billable-Calls: 248
# X-Cost-Per-Request: 0.03
# X-Estimated-Monthly-Cost: 7.4400

πŸ“¦ Batch Request Billing

Batch requests are billed per phone number/review processed, not per HTTP request.

Billing Calculation

Request Type Billing
Single phone lookup 1 API call
Batch lookup (50 numbers) 50 API calls
Single review submit 1 API call
Batch review submit (25 reviews) 25 API calls

Pre-Request Quota Check

Before processing batch requests, the API validates you have sufficient quota:

// Request: Batch lookup with 50 numbers
// Your remaining quota: 30 calls

{
  "success": false,
  "error": {
    "code": "insufficient_quota",
    "message": "This request requires 50 units but you only have 30 remaining",
    "details": {
      "requested": 50,
      "available": 30,
      "upgrade_url": "https://phonetea.com/api-pricing"
    }
  }
}

Why Per-Operation Billing?

Per-operation billing ensures fair pricing:

This applies to all plans including Pay-As-You-Go.


πŸ“ˆ Rate Limit Headers

Every API response includes rate limit or billing information.

Fixed Tier Plans (Starter, Professional, Business, Enterprise)

X-RateLimit-Limit: 6000
X-RateLimit-Remaining: 4950
X-RateLimit-Used: 1050
X-RateLimit-Requested: 1
X-Included-Quota: 1000
X-Included-Used: 1000
X-Purchased-Quota: 5000
X-Purchased-Used: 50
X-RateLimit-Reset: 1735689600
Header Description
X-RateLimit-Limit Your total monthly API call limit (included + purchased)
X-RateLimit-Remaining Calls remaining this month (across both quotas)
X-RateLimit-Used Calls used this month (across both quotas)
X-RateLimit-Requested Units this request will consume
X-Included-Quota Your included Premium calls quota
X-Included-Used Included calls consumed this period
X-Purchased-Quota Your purchased API subscription quota
X-Purchased-Used Purchased calls consumed this period
X-RateLimit-Reset Unix timestamp when limit resets

Pay-As-You-Go Plans

X-Billing-Mode: pay_as_you_go
X-Usage-ThisMonth: 1547
X-Cost-Per-Request: 0.03
X-Estimated-Monthly-Cost: 15.4700
X-Usage-Reset: 1735689600

Handling Rate Limits

When you exceed your rate limit (fixed tiers only):

{
  "success": false,
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Monthly API limit exceeded",
    "details": {
      "limit": 6000,
      "used": 6000,
      "included_quota": 1000,
      "included_used": 1000,
      "purchased_quota": 5000,
      "purchased_used": 5000,
      "resets_at": "2025-02-01T00:00:00Z",
      "upgrade_url": "https://phonetea.com/api-pricing"
    }
  }
}

Best Practice: Monitor X-RateLimit-Remaining and implement exponential backoff:

async function apiCallWithRetry(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fn();
      
      // Check remaining quota
      const remaining = response.headers.get('X-RateLimit-Remaining');
      if (remaining && parseInt(remaining) < 100) {
        console.warn(`Low quota warning: ${remaining} calls remaining`);
      }
      
      return response;
    } catch (error) {
      if (error.status === 429 && i < maxRetries - 1) {
        const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
        await new Promise(r => setTimeout(r, delay));
        continue;
      }
      throw error;
    }
  }
}

🏷️ Review Labels System

PhoneTea uses labels instead of traditional star ratings to categorize phone numbers:

Label Icon Meaning Spam Impact
trollSpamFake ⚠️ Warning - Spam/Scam/Fake number Increases spam score
telemarketer πŸ“ž Warning - Marketing/Sales calls Increases spam score
realPersonFakeNumber ⚠️ Caution - Person using fake identity Neutral
realPersonRealNumber βœ… Safe - Legitimate person Neutral
professional πŸ’Ό Safe - Business/Professional Neutral

Spam Score Calculation

The spam score (0-100) is calculated dynamically:

spam_score = (spam_review_count / total_reviews) Γ— 100

Where spam_review_count = count of (trollSpamFake + telemarketer)

Examples:

Risk Levels

Spam Score Risk Level Recommendation
70-100 high Block or warn strongly
40-69 medium Show caution
0-39 low Safe to answer

πŸ“‘ API Endpoints

Overview

Category Endpoint Method Purpose Billing
Core /v1/phone/lookup GET Get full phone number data 1 call
Core /v1/phone/validate POST Validate phone number 1 call
Core /v1/phone/spam-score GET Get spam score only 1 call
Core /v1/review/submit POST Submit a review 1 call
Search /v1/search GET Search by criteria 1 call
User /v1/user/usage GET Get API usage stats 0 calls (free)
Health /v1/status GET Health check 0 calls (free)
Batch /v1/phone/lookup/batch POST Batch phone lookup N calls (N = numbers count)
Batch /v1/review/submit/batch POST Batch review submit N calls (N = reviews count)
Analytics /v1/analytics/trending GET Get trending numbers 1 call
Analytics /v1/analytics/spam-trends GET Get spam patterns 1 call
Analytics /v1/analytics/top-spam GET Get top spam numbers 1 call
Analytics /v1/analytics/review-stats GET Get review statistics 1 call

πŸ” Core Endpoints

1. Phone Lookup

Get comprehensive information about a phone number including spam score, reviews, carrier data, and location.

Endpoint: GET /v1/phone/lookup

Billing: 1 API call

Query Parameters:

Parameter Type Required Description
number string Yes Phone number (any format accepted)

Request:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://us-east1-project.cloudfunctions.net/api/v1/phone/lookup?number=5551234567"

Success Response (200):

{
  "success": true,
  "data": {
    "number": "5551234567",
    "formatted_number": "(555) 123-4567",
    "spam_score": 75,
    "review_count": 12,
    "most_common_label": "trollSpamFake",
    "risk_level": "high",
    "phone_type": "mobile",
    "carrier": "Verizon Wireless",
    "is_verified": false,
    "city": "Los Angeles",
    "state": "CA",
    "area_code": "555",
    "reviews": [
      {
        "id": "rev_abc123",
        "content": "Spam caller trying to sell insurance",
        "label": "trollSpamFake",
        "username": "JohnDoe",
        "created_at": "2025-01-15T10:30:00.000Z",
        "is_owner_comment": false
      }
    ]
  }
}

Not Found Response (200):

{
  "success": true,
  "data": {
    "number": "5551234567",
    "spam_score": 0,
    "review_count": 0,
    "risk_level": "low",
    "most_common_label": null,
    "reviews": []
  }
}

2. Phone Validation

Validate phone number format and retrieve carrier information.

Endpoint: POST /v1/phone/validate

Billing: 1 API call

Request Body:

{
  "number": "5551234567"
}

Success Response (200):

{
  "success": true,
  "data": {
    "number": "5551234567",
    "valid": true,
    "carrier": "Verizon Wireless",
    "phone_type": "mobile",
    "is_voip": false,
    "region": "US"
  }
}

3. Spam Score

Get just the spam score for a number (lightweight, faster than full lookup).

Endpoint: GET /v1/phone/spam-score

Billing: 1 API call

Query Parameters:

Parameter Type Required Description
number string Yes Phone number to check

Success Response (200):

{
  "success": true,
  "data": {
    "number": "5551234567",
    "spam_score": 75,
    "most_common_label": "trollSpamFake",
    "risk_level": "high"
  }
}

4. Submit Review

Submit a review for a phone number via API.

Endpoint: POST /v1/review/submit

Billing: 1 API call

Request Body:

Field Type Required Description
number string Yes Phone number
content string Yes Review text
label string Yes Review label (see valid labels below)
author string No Author name (defaults to β€œAPI User”)

Valid Labels:

Request:

curl -X POST \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "number": "5551234567",
    "content": "Spam caller selling insurance",
    "label": "trollSpamFake",
    "author": "My Call Blocker App"
  }' \
  "https://us-east1-project.cloudfunctions.net/api/v1/review/submit"

Success Response (200):

{
  "success": true,
  "data": {
    "review_id": "rev_xyz789",
    "message": "Review submitted successfully",
    "number": "5551234567",
    "label": "trollSpamFake"
  }
}

5. Search

Search for phone numbers by area code, city, state, or number prefix.

Endpoint: GET /v1/search

Billing: 1 API call

Query Parameters:

Parameter Type Required Description
query string Yes Search query
type string No Search type: number, area_code, city, state
limit integer No Max results (default: 10, max: 50)

Request Examples:

# Search by area code
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.../v1/search?query=555&type=area_code&limit=20"

# Search by city
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.../v1/search?query=Los%20Angeles&type=city"

Success Response (200):

{
  "success": true,
  "data": {
    "query": "555",
    "type": "area_code",
    "total_results": 15,
    "results": [
      {
        "number": "5551234567",
        "city": "Los Angeles",
        "state": "CA",
        "review_count": 12,
        "spam_score": 75
      }
    ]
  }
}

6. Usage Statistics

Get your API usage statistics and rate limit information.

Endpoint: GET /v1/user/usage

Billing: Free (0 API calls)

Success Response (200):

{
  "success": true,
  "data": {
    "api_key_name": "Production API Key",
    "key_type": "production",
    "plan": "starter",
    "billing_mode": "fixed",
    "usage": {
      "today": 145,
      "this_month": 3842,
      "included_quota": 1000,
      "included_used": 1000,
      "included_remaining": 0,
      "purchased_quota": 5000,
      "purchased_used": 2842,
      "purchased_remaining": 2158,
      "total_limit": 6000,
      "total_remaining": 2158,
      "key_calls_today": 45,
      "key_calls_this_month": 1200
    },
    "subscription": {
      "premium_tier": "yearly",
      "api_tier": "starter",
      "discount_applied": 15,
      "next_billing_date": "2025-02-01T00:00:00Z"
    },
    "last_30_days": {
      "total_calls": 4123,
      "successful": 4098,
      "failed": 25,
      "by_endpoint": {
        "/v1/phone/lookup": { "successful": 2500, "failed": 10 },
        "/v1/phone/spam-score": { "successful": 1200, "failed": 5 },
        "/v1/review/submit": { "successful": 398, "failed": 10 }
      }
    },
    "created_at": "2024-12-01T00:00:00.000Z",
    "last_used": "2025-01-15T14:23:10.000Z"
  }
}

PAYG Usage Response:

{
  "success": true,
  "data": {
    "api_key_name": "Production API Key",
    "key_type": "production",
    "plan": "payAsYouGo",
    "billing_mode": "pay_as_you_go",
    "usage": {
      "today": 45,
      "this_month": 1547,
      "included_quota": 1000,
      "included_used": 1000,
      "included_remaining": 0,
      "purchased_quota": "unlimited",
      "purchased_used": 547,
      "purchased_remaining": "unlimited",
      "total_limit": "unlimited",
      "total_remaining": "unlimited",
      "cost_this_month": 16.41,
      "cost_per_call": 0.03
    },
    "subscription": {
      "premium_tier": "lifetime",
      "api_tier": "payAsYouGo",
      "discount_applied": 20,
      "next_billing_date": "2025-02-01T00:00:00Z"
    }
  }
}

7. Health Check

Check API status (no authentication required).

Endpoint: GET /v1/status

Billing: Free (0 API calls, no auth required)

Success Response (200):

{
  "success": true,
  "status": "operational",
  "version": "1.1.0",
  "time": "2025-12-16T14:30:00.000Z"
}

πŸ“¦ Batch Endpoints

8. Batch Phone Lookup

Look up multiple phone numbers in a single request.

Endpoint: POST /v1/phone/lookup/batch

Billing: N API calls (where N = number of phone numbers)

Limits:

Request:

curl -X POST \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"numbers": ["5551234567", "5559876543", "5555555555"]}' \
  "https://us-east1-project.cloudfunctions.net/api/v1/phone/lookup/batch"

Success Response (200):

{
  "success": true,
  "data": {
    "total_requested": 3,
    "successful": 3,
    "failed": 0,
    "billing": {
      "calls_consumed": 3,
      "remaining_quota": 4997
    },
    "results": [
      {
        "number": "5551234567",
        "formatted_number": "(555) 123-4567",
        "spam_score": 75,
        "review_count": 12,
        "most_common_label": "trollSpamFake",
        "risk_level": "high"
      },
      {
        "number": "5559876543",
        "formatted_number": "(555) 987-6543",
        "spam_score": 20,
        "review_count": 3,
        "most_common_label": "professional",
        "risk_level": "low"
      },
      {
        "number": "5555555555",
        "formatted_number": "(555) 555-5555",
        "spam_score": 0,
        "review_count": 0,
        "most_common_label": null,
        "risk_level": "low"
      }
    ]
  }
}

Insufficient Quota Response (402):

{
  "success": false,
  "error": {
    "code": "insufficient_quota",
    "message": "This request requires 100 units but you only have 50 remaining",
    "details": {
      "requested": 100,
      "available": 50,
      "upgrade_url": "https://phonetea.com/api-pricing"
    }
  }
}

9. Batch Review Submit

Submit multiple reviews in a single request.

Endpoint: POST /v1/review/submit/batch

Billing: N API calls (where N = number of reviews)

Limits:

Request:

curl -X POST \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reviews": [
      {"number": "5551234567", "content": "Spam caller", "label": "trollSpamFake"},
      {"number": "5559876543", "content": "Legit business", "label": "professional"}
    ]
  }' \
  "https://us-east1-project.cloudfunctions.net/api/v1/review/submit/batch"

Success Response (200):

{
  "success": true,
  "data": {
    "total_requested": 2,
    "successful": 2,
    "failed": 0,
    "billing": {
      "calls_consumed": 2,
      "remaining_quota": 4998
    },
    "results": [
      {"index": 0, "review_id": "rev_abc123", "number": "5551234567", "label": "trollSpamFake"},
      {"index": 1, "review_id": "rev_xyz789", "number": "5559876543", "label": "professional"}
    ],
    "message": "Successfully submitted 2 reviews"
  }
}

Partial Success Response (200):

{
  "success": true,
  "data": {
    "total_requested": 3,
    "successful": 2,
    "failed": 1,
    "billing": {
      "calls_consumed": 2,
      "remaining_quota": 4998
    },
    "results": [
      {"index": 0, "review_id": "rev_abc123", "number": "5551234567", "label": "trollSpamFake"},
      {"index": 2, "review_id": "rev_def456", "number": "5555555555", "label": "professional"}
    ],
    "errors": [
      {"index": 1, "number": "5559876543", "error": "Invalid label provided"}
    ],
    "message": "Successfully submitted 2 reviews"
  }
}

πŸ“Š Analytics Endpoints

10. Trending Numbers

Get the most searched or reviewed phone numbers in a time period.

Endpoint: GET /v1/analytics/trending

Billing: 1 API call

Query Parameters:

Parameter Type Required Default Description
limit integer No 20 Max results (max: 100)
period string No 7d Time period: 24h, 7d, 30d

Success Response (200):

{
  "success": true,
  "data": {
    "period": "7d",
    "total_results": 10,
    "results": [
      {
        "number": "5551234567",
        "formatted_number": "(555) 123-4567",
        "recent_reviews": 45,
        "total_reviews": 127,
        "spam_score": 85,
        "most_common_label": "trollSpamFake",
        "risk_level": "high",
        "city": "Los Angeles",
        "state": "CA"
      }
    ]
  }
}

11. Spam Trends

Get spam patterns and trends over time.

Endpoint: GET /v1/analytics/spam-trends

Billing: 1 API call

Query Parameters:

Parameter Type Required Default Description
period string No 30d Time period: 7d, 30d, 90d

Success Response (200):

{
  "success": true,
  "data": {
    "period": "30d",
    "group_by": "day",
    "overall_stats": {
      "total_reviews": 5432,
      "spam_reviews": 3215,
      "spam_rate": 59,
      "label_distribution": {
        "trollSpamFake": 2105,
        "telemarketer": 1110,
        "realPersonFakeNumber": 487,
        "realPersonRealNumber": 1230,
        "professional": 500
      }
    },
    "time_series": [
      {
        "date": "2025-10-16",
        "total_reviews": 180,
        "spam_reviews": 110,
        "spam_percentage": 61
      }
    ]
  }
}

12. Top Spam Numbers

Get phone numbers with the highest spam scores.

Endpoint: GET /v1/analytics/top-spam

Billing: 1 API call

Query Parameters:

Parameter Type Required Default Description
limit integer No 20 Max results (max: 100)
min_reviews integer No 3 Minimum reviews required

Success Response (200):

{
  "success": true,
  "data": {
    "total_results": 10,
    "min_reviews": 5,
    "results": [
      {
        "number": "5551234567",
        "formatted_number": "(555) 123-4567",
        "spam_score": 95,
        "review_count": 48,
        "most_common_label": "trollSpamFake",
        "risk_level": "high",
        "city": "Los Angeles",
        "state": "CA"
      }
    ]
  }
}

13. Review Label Statistics

Get distribution and breakdown of review labels over time.

Endpoint: GET /v1/analytics/review-stats

Billing: 1 API call

Query Parameters:

Parameter Type Required Default Description
period string No 30d Time period: 24h, 7d, 30d, 90d, all

Success Response (200):

{
  "success": true,
  "data": {
    "period": "30d",
    "total_reviews": 5432,
    "unique_numbers": 2187,
    "spam_reviews": 3215,
    "spam_percentage": 59,
    "label_distribution": [
      {"label": "trollSpamFake", "count": 2105, "percentage": 39},
      {"label": "telemarketer", "count": 1110, "percentage": 20},
      {"label": "realPersonRealNumber", "count": 1230, "percentage": 23},
      {"label": "professional", "count": 500, "percentage": 9},
      {"label": "realPersonFakeNumber", "count": 487, "percentage": 9}
    ]
  }
}

🚨 Error Handling

HTTP Status Codes

Code Meaning Description
200 OK Request successful
400 Bad Request Invalid request parameters
401 Unauthorized Missing or invalid API key
402 Payment Required Insufficient quota for batch request
403 Forbidden Premium subscription required
429 Too Many Requests Rate limit exceeded
500 Internal Server Error Server error

Error Response Format

All errors follow this format:

{
  "success": false,
  "error": {
    "code": "error_code",
    "message": "Human-readable error message",
    "details": { }
  }
}

Common Error Codes

Error Code HTTP Status Description
unauthorized 401 Invalid or missing API key
premium_required 403 API access requires Premium subscription
rate_limit_exceeded 429 Monthly rate limit exceeded
insufficient_quota 402 Not enough quota for batch request
invalid_request 400 Missing or invalid parameters
invalid_label 400 Invalid review label provided
internal_error 500 Server error

Error Examples

401 Unauthorized:

{
  "success": false,
  "error": {
    "code": "unauthorized",
    "message": "Invalid API key"
  }
}

403 Premium Required:

{
  "success": false,
  "error": {
    "code": "premium_required",
    "message": "API access requires an active Premium subscription",
    "details": {
      "upgrade_url": "https://phonetea.com/premium"
    }
  }
}

429 Rate Limit Exceeded:

{
  "success": false,
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Monthly API limit exceeded",
    "details": {
      "limit": 6000,
      "used": 6000,
      "included_quota": 1000,
      "included_used": 1000,
      "purchased_quota": 5000,
      "purchased_used": 5000,
      "resets_at": "2025-02-01T00:00:00Z",
      "upgrade_url": "https://phonetea.com/api-pricing"
    }
  }
}

402 Insufficient Quota:

{
  "success": false,
  "error": {
    "code": "insufficient_quota",
    "message": "This request requires 50 units but you only have 30 remaining",
    "details": {
      "requested": 50,
      "available": 30,
      "upgrade_url": "https://phonetea.com/api-pricing"
    }
  }
}

πŸ”„ Subscription Management

Upgrading Your API Tier

You can upgrade your API subscription at any time:

  1. Log in to your PhoneTea account
  2. Navigate to Settings β†’ Developer β†’ API Subscription
  3. Select a higher tier
  4. Complete payment (discount applied automatically)

Effect: Changes take effect immediately. Your API key limits are updated instantly.

Downgrading Your API Tier

  1. Navigate to Settings β†’ Developer β†’ API Subscription
  2. Select a lower tier or cancel

Effect: Downgrade takes effect at the end of your current billing period. You keep your current limits until then.

Cancellation Scenarios

Action What Happens
Cancel API Subscription (Keep Premium) API subscription ends at period end. Key reverts to Premium-only quota (500-2,500). Key remains active.
Cancel Premium Subscription Immediately cancels both Premium AND any API subscription. All API keys deactivated. All API access revoked.
Premium Refund Immediate full downgrade. All API keys deactivated. Same as cancellation but instant.
API Subscription Refund Loses API tier quota. Keeps Premium status and quota. Key updated with reduced limits.

Important Notes


πŸ’» Code Examples

JavaScript / Node.js

class PhoneTeaAPI {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://us-east1-{project-id}.cloudfunctions.net/api';
  }

  async request(endpoint, options = {}) {
    const url = `${this.baseUrl}${endpoint}`;
    const headers = {
      'Authorization': `Bearer ${this.apiKey}`,
      'Content-Type': 'application/json',
      ...options.headers
    };

    const response = await fetch(url, { ...options, headers });
    const data = await response.json();
    
    // Log rate limit info
    const remaining = response.headers.get('X-RateLimit-Remaining');
    if (remaining && parseInt(remaining) < 100) {
      console.warn(`⚠️ Low quota: ${remaining} calls remaining`);
    }
    
    return data;
  }

  async lookup(phoneNumber) {
    return this.request(`/v1/phone/lookup?number=${phoneNumber}`);
  }

  async getSpamScore(phoneNumber) {
    return this.request(`/v1/phone/spam-score?number=${phoneNumber}`);
  }

  async submitReview(phoneNumber, content, label, author = 'API User') {
    return this.request('/v1/review/submit', {
      method: 'POST',
      body: JSON.stringify({ number: phoneNumber, content, label, author })
    });
  }

  async batchLookup(numbers) {
    return this.request('/v1/phone/lookup/batch', {
      method: 'POST',
      body: JSON.stringify({ numbers })
    });
  }

  async getUsage() {
    return this.request('/v1/user/usage');
  }
}

// Usage
const api = new PhoneTeaAPI(process.env.PHONETEA_API_KEY);

// Single lookup
const result = await api.lookup('5551234567');
console.log(`Spam Score: ${result.data.spam_score}%`);

// Batch lookup (billed as 3 calls)
const batchResult = await api.batchLookup(['5551234567', '5559876543', '5555555555']);
console.log(`Processed ${batchResult.data.successful} numbers`);

// Check usage
const usage = await api.getUsage();
console.log(`Remaining: ${usage.data.usage.remaining} / ${usage.data.usage.total_limit}`);

Python

import requests
from typing import List, Optional

class PhoneTeaAPI:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.base_url = 'https://us-east1-{project-id}.cloudfunctions.net/api'
        self.headers = {
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json'
        }

    def _request(self, endpoint: str, method: str = 'GET', data: dict = None):
        url = f'{self.base_url}{endpoint}'
        
        if method == 'GET':
            response = requests.get(url, headers=self.headers)
        else:
            response = requests.post(url, headers=self.headers, json=data)
        
        # Check rate limits
        remaining = response.headers.get('X-RateLimit-Remaining')
        if remaining and int(remaining) < 100:
            print(f"⚠️ Low quota warning: {remaining} calls remaining")
        
        return response.json()

    def lookup(self, phone_number: str):
        return self._request(f'/v1/phone/lookup?number={phone_number}')

    def get_spam_score(self, phone_number: str):
        return self._request(f'/v1/phone/spam-score?number={phone_number}')

    def submit_review(self, phone_number: str, content: str, label: str, author: str = 'API User'):
        return self._request('/v1/review/submit', 'POST', {
            'number': phone_number,
            'content': content,
            'label': label,
            'author': author
        })

    def batch_lookup(self, numbers: List[str]):
        return self._request('/v1/phone/lookup/batch', 'POST', {'numbers': numbers})

    def get_usage(self):
        return self._request('/v1/user/usage')


# Usage
import os
api = PhoneTeaAPI(os.environ['PHONETEA_API_KEY'])

# Single lookup
result = api.lookup('5551234567')
print(f"Spam Score: {result['data']['spam_score']}%")

# Batch lookup (billed as 3 calls)
batch_result = api.batch_lookup(['5551234567', '5559876543', '5555555555'])
print(f"Processed {batch_result['data']['successful']} numbers")

cURL Examples

# Set your API key
export PHONETEA_API_KEY="your_api_key_here"

# Single lookup
curl -H "Authorization: Bearer $PHONETEA_API_KEY" \
  "https://us-east1-project.cloudfunctions.net/api/v1/phone/lookup?number=5551234567"

# Spam score only (faster)
curl -H "Authorization: Bearer $PHONETEA_API_KEY" \
  "https://us-east1-project.cloudfunctions.net/api/v1/phone/spam-score?number=5551234567"

# Submit review
curl -X POST \
  -H "Authorization: Bearer $PHONETEA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"number":"5551234567","content":"Spam caller","label":"trollSpamFake"}' \
  "https://us-east1-project.cloudfunctions.net/api/v1/review/submit"

# Batch lookup (billed as N calls)
curl -X POST \
  -H "Authorization: Bearer $PHONETEA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"numbers":["5551234567","5559876543"]}' \
  "https://us-east1-project.cloudfunctions.net/api/v1/phone/lookup/batch"

# Check usage (free)
curl -H "Authorization: Bearer $PHONETEA_API_KEY" \
  "https://us-east1-project.cloudfunctions.net/api/v1/user/usage"

🎯 Use Cases

1. Real-Time Call Screening

async function screenIncomingCall(phoneNumber) {
  const api = new PhoneTeaAPI(process.env.PHONETEA_API_KEY);
  
  // Quick spam check (1 API call)
  const result = await api.getSpamScore(phoneNumber);
  const { spam_score, risk_level } = result.data;
  
  if (risk_level === 'high') {
    return { action: 'BLOCK', reason: `High spam risk (${spam_score}%)` };
  } else if (risk_level === 'medium') {
    return { action: 'WARN', reason: `Medium risk (${spam_score}%)` };
  }
  return { action: 'ALLOW', reason: 'Low risk' };
}

2. Batch Contact Analysis

async function analyzeContactList(contacts) {
  const api = new PhoneTeaAPI(process.env.PHONETEA_API_KEY);
  
  // Check quota first
  const usage = await api.getUsage();
  if (usage.data.usage.remaining < contacts.length) {
    throw new Error(`Insufficient quota: need ${contacts.length}, have ${usage.data.usage.remaining}`);
  }
  
  // Process in batches of 100
  const results = [];
  for (let i = 0; i < contacts.length; i += 100) {
    const batch = contacts.slice(i, i + 100);
    const response = await api.batchLookup(batch);
    results.push(...response.data.results);
  }
  
  // Find risky contacts
  return results.filter(r => r.spam_score >= 40);
}

πŸ›‘οΈ Best Practices

Security

Performance

Cost Optimization


πŸ“ž Support

Response Times:


πŸ”„ Changelog

Version 1.2.0 (March 2026)

Multi-Bucket Quota System:

API Key Management:

Quota Enforcement:

Version 1.1.0 (December 16, 2025)

Pricing & Billing Updates:

New Features:

Version 1.0.0 (November 15, 2025)

Initial Release:


πŸ“œ Terms & Privacy


Built with ❀️ by the PhoneTea Team

Β© 2025-2026 PhoneTea. All rights reserved.