# AutoSMS API

Programmatic access to AutoSMS — rent US phone numbers for **DoorDash**,
**Chick-fil-A**, and **Uber**, fetch their OTP codes, cancel for a refund, and
check your balance.

- **Base URL:** `https://autosms.live`
- **Format:** JSON request bodies, JSON responses. Send `Content-Type: application/json` on POSTs.
- **Money:** all dollar amounts are decimals (e.g. `5.0` = $5.00).
- **Time:** `expiredAt` is a Unix timestamp (seconds, UTC); `expiredAt_est` is a human-readable EST string.

---

## Authentication

Every endpoint except the health check requires your personal API key in the
`x-api-key` header.

```
x-api-key: asms_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

Get or view your key in Discord: open the panel and press **🔐 API Key**. The
key is stable — pressing the button again returns the same key (it does not
rotate). Your API balance, rentals, and history are the same account you use in
Discord.

The header name is case-insensitive; `X-API-KEY`, `api_key`, and `API_KEY` are
also accepted.

### Auth errors

| Status | Body | Meaning |
|--------|------|---------|
| `401` | `{"detail": "Unauthorized - missing API key"}` | No key sent |
| `401` | `{"detail": "Unauthorized - invalid API key"}` | Key not recognized |

---

## Services

`service` accepts the canonical name or a common alias:

| Canonical | Accepted aliases |
|-----------|------------------|
| `DoorDash` | `doordash`, `door dash` |
| `ChickFilA` | `chick-fil-a`, `chick fil a`, `chickfila`, `cfa` |
| `Uber` | `uber` |

---

## Endpoints

### `POST /balance`

Your current credit balance.

**Request:** empty body.

**200 OK**
```json
{
  "status": "success",
  "user_id": "1306300782123159674",
  "username": "vinixeeee",
  "balance": 25.0
}
```

```sh
curl -sS https://autosms.live/balance -X POST \
  -H "x-api-key: YOUR_KEY"
```

---

### `POST /getnumber`

Rent a fresh US number for a service. Your balance is charged immediately
(service price + per-sale fees). If no code ever arrives, the rental is
auto-refunded when it expires.

**Request**
```json
{ "service": "DoorDash" }
```

**200 OK**
```json
{
  "success": true,
  "service": "DoorDash",
  "PhoneNumber": "9049362804",
  "CountryCode": "+1",
  "DirectResponse": false,
  "expiredAt": 1730000000,
  "expiredAt_est": "2024-10-27 12:00:00 PM EST",
  "rental_minutes": 10,
  "balance_before": 100.0,
  "balance_after": 95.5,
  "charged": 4.5
}
```

**Errors** — returned as `{"status":"error","code":"<code>","message":"<text>"}`
with the matching HTTP status:

| Status | `code` | When |
|--------|--------|------|
| `400` | — (`{"detail":"Missing service"}`) | Empty `service` |
| `400` | `unknown_service` | Service name not recognized / not configured |
| `402` | `insufficient_balance` | Balance too low for the charge |
| `402` | `spend_cap` | Your admin-set daily spend cap would be exceeded |
| `404` | `out_of_stock` | No numbers available for that service |
| `502` | `upstream` | Carrier error |

```sh
curl -sS https://autosms.live/getnumber -X POST \
  -H "x-api-key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"service":"DoorDash"}'
```

---

### `POST /smscode`

Fetch the latest OTP for a number you rented. Poll this every few seconds after
`/getnumber` until you get `new_code`.

**Request**
```json
{ "phone_number": "9049362804" }
```

**200 OK** — one of these shapes (`status` tells you which):

**Code arrived**
```json
{
  "status": "new_code",
  "code": "123456",
  "phone_number": "9049362804",
  "country_code": "+1",
  "service": "doordash",
  "expiredAt": 1730000000,
  "expiredAt_est": "2024-10-27 12:00:00 PM EST"
}
```

**No code yet** — keep polling
```json
{
  "status": "no_code",
  "message": "No code received yet.",
  "phone_number": "9049362804",
  "service": "doordash"
}
```

**Expired with no code — auto-refunded**
```json
{
  "status": "expired_refunded",
  "phone_number": "9049362804",
  "country_code": "+1",
  "service": "doordash",
  "refunded": 4.5,
  "balance_after": 100.0
}
```

**No active rental** (never rented, wrong owner, or already closed)
```json
{
  "status": "not_found",
  "message": "No active rental found for this number."
}
```

**Errors:** `400` `{"detail":"Missing phone_number"}`, plus the standard `401`.

```sh
curl -sS https://autosms.live/smscode -X POST \
  -H "x-api-key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"phone_number":"9049362804"}'
```

---

### `POST /cancelsms`

Cancel an active rental. You're refunded **only if the carrier accepts the
cancellation** (i.e. it didn't already deliver a code or close the rental).

**Request**
```json
{ "phone_number": "9049362804" }
```

**200 OK — cancelled & refunded**
```json
{
  "success": true,
  "status": "cancelled",
  "phone_number": "9049362804",
  "country_code": "+1",
  "service": "doordash",
  "code_received": false,
  "refunded": 4.5,
  "balance_before": 95.5,
  "balance_after": 100.0,
  "upstream_message": "cancelled"
}
```

**200 OK — not cancelled** (`success:false`); `status` explains why:

| `status` | Meaning |
|----------|---------|
| `already_refunded` | A previous cancel already refunded this rental |
| `code_received` | A code already arrived — non-refundable |
| `upstream_refused` | Carrier refused (e.g. cancel window passed) — no refund |
| `upstream_error` | Couldn't reach the carrier — try again |
| `not_found` | No active rental for this number |

```json
{
  "success": false,
  "status": "code_received",
  "message": "Code already arrived for this rental — no refund issued.",
  "phone_number": "9049362804",
  "country_code": "+1",
  "service": "doordash",
  "code_received": true,
  "refunded": 0.0,
  "balance_before": 95.5,
  "balance_after": 95.5
}
```

**Errors:** `400` `{"detail":"Missing phone_number"}`, `401`.

```sh
curl -sS https://autosms.live/cancelsms -X POST \
  -H "x-api-key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"phone_number":"9049362804"}'
```

---

### `POST /resend`

Request **another OTP on a number you already used**. Used numbers stay
resendable for several days. A resend is often **free**; sometimes it costs a
small reactivation fee.

Two-step for paid resends: call without `confirm` to learn the cost, then call
again with `"confirm": true` to authorize the charge. Free resends happen
immediately on the first call.

**Request**
```json
{ "phone_number": "9049362804" }
```

**200 OK — free resend done**
```json
{ "status": "resent", "phone_number": "9049362804", "service": "doordash",
  "message": "Resend requested — the new code will arrive shortly." }
```
After `resent`, poll `POST /smscode` for the new code.

**200 OK — paid resend available** (not yet charged)
```json
{ "status": "costs", "service": "doordash", "phone_number": "9049362804",
  "cost_cents": 5, "charge_cents": 10, "expires_in_hour": 97 }
```
`charge_cents` is what your balance will be charged if you confirm.

| `status` | Meaning |
|----------|---------|
| `resent` | Free resend accepted — poll `/smscode` for the new code |
| `costs` | Paid resend available — resend with `"confirm": true` to charge `charge_cents` |
| `needs_new` | Can't be reactivated — rent fresh via `/repeat` |
| `not_found` | No rental found for this number |

**Confirm a paid resend** — charges your balance, then resends:
```json
{ "phone_number": "9049362804", "confirm": true }
```
Returns `resent` (with `charged`), or `{"status":"insufficient","charge_cents":...,"balance_cents":...}`.

**Errors:** `400` `{"detail":"Missing phone_number"}`, `401`.

```sh
# check cost / free resend
curl -sS https://autosms.live/resend -X POST \
  -H "x-api-key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"phone_number":"9049362804"}'

# confirm a paid resend
curl -sS https://autosms.live/resend -X POST \
  -H "x-api-key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"phone_number":"9049362804","confirm":true}'
```

---

### `POST /repeat`

Re-rent based on a number from a **past completed** rental (one that delivered a
code). The carrier can't always return the exact same MSISDN, so this rents a
fresh number for the same service. Response shape matches `/getnumber` plus
`"repeat": true`.

**Request**
```json
{ "phone_number": "9049362804" }
```

**200 OK**
```json
{
  "success": true,
  "repeat": true,
  "service": "DoorDash",
  "PhoneNumber": "2542255894",
  "CountryCode": "+1",
  "DirectResponse": false,
  "expiredAt": 1730000600,
  "expiredAt_est": "2024-10-27 12:10:00 PM EST",
  "rental_minutes": 10,
  "balance_before": 100.0,
  "balance_after": 95.5,
  "charged": 4.5
}
```

**Errors** — same `{"status":"error","code":...}` shape as `/getnumber`, plus:

| Status | `code` | When |
|--------|--------|------|
| `404` | `no_repeat` | No qualifying past rental for that number |
| `400` | — (`{"detail":"Missing phone_number"}`) | Empty `phone_number` |
| `402` | `insufficient_balance` / `spend_cap` | Same as `/getnumber` |
| `404` | `out_of_stock` | Same as `/getnumber` |

```sh
curl -sS https://autosms.live/repeat -X POST \
  -H "x-api-key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"phone_number":"9049362804"}'
```

---

### `GET /smsservices`

List available services with indicative pricing and stock.

**Request:** no body. Requires `x-api-key`.

**200 OK**
```json
{
  "services": [
    {
      "service": "DoorDash",
      "price": 0.2,
      "max_rental": 10,
      "rental_time_minutes": 10,
      "stock": 11000
    }
  ],
  "count": 1
}
```

`price` is indicative and may be `null` if the carrier hasn't quoted one; the
exact price is whatever `/getnumber` actually charges (`charged`). `stock` is
the live count of available numbers.

```sh
curl -sS https://autosms.live/smsservices -H "x-api-key: YOUR_KEY"
```

---

### `GET /` — health check

No auth. Returns `{"status":"ok","service":"autosms"}`.

---

## Typical flow

```
1. POST /getnumber  {"service":"DoorDash"}   → get PhoneNumber, charged
2. (use the number to trigger the platform's SMS)
3. POST /smscode    {"phone_number":"..."}   → poll until status == "new_code"
4. (use code)  — or, if it never arrives, it auto-refunds at expiry
```

If the number is unusable, call `POST /cancelsms` before it expires for a refund.

## Notes

- All actions hit the **same account** as your Discord usage — shared balance,
  rentals, and history.
- Numbers are **US-only**. Each rental lasts `rental_minutes` (default 10).
- A rental that never receives a code is **auto-refunded** at expiry; you don't
  need to poll forever.
- Concurrency is fine — you can rent multiple numbers in parallel. Each is
  charged independently and balance can't go negative.
