{
 "openapi": "3.1.0",
 "info": {
  "title": "Spam I Am API",
  "version": "1.1.0",
  "description": "Check whether a phone number shows a spam label on AT&T, Verizon and T-Mobile. Start a check, call each test line from the number being checked (the API cannot place calls), then poll the check until status is complete. The first check on a number needs no key. Docs: https://ismynumberspam.com/docs/api"
 },
 "servers": [
  {
   "url": "https://ismynumberspam.com"
  }
 ],
 "components": {
  "securitySchemes": {
   "apiKey": {
    "type": "http",
    "scheme": "bearer",
    "description": "A key from the Balance page, starting sia_"
   }
  },
  "parameters": {
   "token": {
    "name": "token",
    "in": "query",
    "required": false,
    "schema": {
     "type": "string"
    },
    "description": "For a keyless check: the token returned when it was started (starts ct_)"
   }
  },
  "schemas": {
   "Error": {
    "type": "object",
    "properties": {
     "error": {
      "type": "object",
      "required": [
       "code",
       "message"
      ],
      "properties": {
       "code": {
        "type": "string",
        "enum": [
         "invalid_number",
         "invalid_carriers",
         "invalid_json",
         "test_line",
         "api_key_required",
         "invalid_api_key",
         "insufficient_funds",
         "not_found",
         "free_check_used",
         "too_soon",
         "too_many_open",
         "daily_limit",
         "free_limit",
         "no_lines",
         "too_large",
         "method_not_allowed",
         "invalid_webhook_url",
         "key_limit",
         "invalid_reason",
         "invalid_amount",
         "handoff_limit"
        ]
       },
       "message": {
        "type": "string"
       },
       "price_cents": {
        "type": "integer"
       },
       "available_cents": {
        "type": "integer"
       },
       "top_up_url": {
        "type": "string"
       },
       "limit_cents": {
        "type": "integer"
       },
       "spent_cents": {
        "type": "integer"
       },
       "ask_human": {
        "type": "string"
       }
      }
     }
    }
   },
   "Call": {
    "type": "object",
    "required": [
     "carrier",
     "dial",
     "status"
    ],
    "properties": {
     "carrier": {
      "type": "string",
      "enum": [
       "AT&T",
       "Verizon",
       "T-Mobile"
      ]
     },
     "dial": {
      "type": "string",
      "description": "The test line to call from the number being checked (E.164)"
     },
     "status": {
      "type": "string",
      "enum": [
       "waiting",
       "complete",
       "incomplete"
      ]
     },
     "seconds_left": {
      "type": "integer"
     },
     "flagged": {
      "type": "boolean"
     },
     "label": {
      "type": [
       "string",
       "null"
      ],
      "description": "The spam label shown, such as Spam Risk"
     },
     "caller_name": {
      "type": [
       "string",
       "null"
      ]
     },
     "reason": {
      "type": "string",
      "enum": [
       "no_call",
       "unreadable_screen"
      ]
     },
     "screenshot_url": {
      "type": "string"
     },
     "checked_at": {
      "type": "string"
     }
    }
   },
   "Check": {
    "type": "object",
    "required": [
     "id",
     "number",
     "status",
     "calls"
    ],
    "properties": {
     "id": {
      "type": "string"
     },
     "number": {
      "type": "string",
      "description": "The number being checked (E.164)"
     },
     "status": {
      "type": "string",
      "enum": [
       "waiting_for_calls",
       "complete"
      ]
     },
     "created_at": {
      "type": "string"
     },
     "expires_at": {
      "type": "string"
     },
     "flagged": {
      "type": [
       "boolean",
       "null"
      ],
      "description": "True if any carrier shows a spam label; null if no carrier returned a result"
     },
     "flagged_on": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "calls": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/Call"
      }
     },
     "cost": {
      "type": "object",
      "properties": {
       "free": {
        "type": "boolean"
       },
       "held_cents": {
        "type": "integer"
       },
       "charged_cents": {
        "type": [
         "integer",
         "null"
        ]
       }
      }
     },
     "url": {
      "type": "string"
     },
     "token": {
      "type": "string",
      "description": "Keyless checks only: needed to read this check"
     },
     "instructions": {
      "type": "string"
     },
     "poll_after_seconds": {
      "type": "integer"
     },
     "webhook": {
      "type": "object",
      "properties": {
       "url": {
        "type": "string"
       },
       "status": {
        "type": "string",
        "enum": [
         "pending",
         "delivered",
         "failed"
        ]
       },
       "attempts": {
        "type": "integer"
       },
       "last_error": {
        "type": [
         "string",
         "null"
        ]
       },
       "secret": {
        "type": "string",
        "description": "Only in the answer to POST /v1/checks"
       }
      }
     }
    }
   },
   "Handoff": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string"
     },
     "status": {
      "type": "string",
      "enum": [
       "pending",
       "approved",
       "declined",
       "expired"
      ]
     },
     "approve_url": {
      "type": "string",
      "description": "Show this to your human"
     },
     "token": {
      "type": "string",
      "description": "Only in the answer to POST: needed to read a keyless request"
     },
     "api_key": {
      "type": "string",
      "description": "Once approved (keyless requests only): your new key, shown once"
     },
     "key_spend_limit_cents": {
      "type": [
       "integer",
       "null"
      ]
     },
     "reason": {
      "type": [
       "string",
       "null"
      ]
     },
     "number": {
      "type": [
       "string",
       "null"
      ]
     },
     "amount_cents": {
      "type": [
       "integer",
       "null"
      ]
     },
     "created_at": {
      "type": "string"
     },
     "expires_at": {
      "type": "string"
     },
     "decided_at": {
      "type": [
       "string",
       "null"
      ]
     },
     "instructions": {
      "type": "string"
     }
    }
   }
  }
 },
 "paths": {
  "/v1/checks": {
   "post": {
    "operationId": "startCheck",
    "summary": "Start a check",
    "description": "Without a key, uses the number's free first check and returns a token. With a key, the price is held from the balance and charged only for carriers that return a result.",
    "security": [
     {},
     {
      "apiKey": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "number"
        ],
        "properties": {
         "number": {
          "type": "string",
          "description": "US 10-digit number you will call from",
          "examples": [
           "2145550100"
          ]
         },
         "carriers": {
          "type": "array",
          "items": {
           "type": "string",
           "enum": [
            "AT&T",
            "Verizon",
            "T-Mobile"
           ]
          },
          "description": "Leave out to check every online carrier"
         },
         "webhook_url": {
          "type": "string",
          "description": "https address to POST the finished check to (signed with the returned webhook.secret)"
         }
        }
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "The check",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Check"
        }
       }
      }
     },
     "400": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "402": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "409": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "503": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/v1/checks/{id}": {
   "get": {
    "operationId": "getCheck",
    "summary": "Get a check and its results",
    "description": "Poll every 5 seconds while status is waiting_for_calls.",
    "security": [
     {},
     {
      "apiKey": []
     }
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "$ref": "#/components/parameters/token"
     }
    ],
    "responses": {
     "200": {
      "description": "The check",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Check"
        }
       }
      }
     },
     "401": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/v1/checks/{id}/screenshots/{result}.jpg": {
   "get": {
    "operationId": "getScreenshot",
    "summary": "A carrier's screenshot",
    "security": [
     {},
     {
      "apiKey": []
     }
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "result",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "$ref": "#/components/parameters/token"
     }
    ],
    "responses": {
     "200": {
      "description": "JPEG",
      "content": {
       "image/jpeg": {}
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/v1/balance": {
   "get": {
    "operationId": "getBalance",
    "summary": "Balance in cents",
    "security": [
     {
      "apiKey": []
     }
    ],
    "responses": {
     "200": {
      "description": "Balance",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "balance_cents": {
           "type": "integer"
          },
          "held_cents": {
           "type": "integer"
          },
          "available_cents": {
           "type": "integer"
          },
          "currency": {
           "type": "string"
          },
          "top_up_url": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "401": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/v1/coverage": {
   "get": {
    "operationId": "getCoverage",
    "summary": "Carriers online, prices and limits",
    "security": [
     {}
    ],
    "responses": {
     "200": {
      "description": "Coverage",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    }
   }
  },
  "/v1/handoffs": {
   "post": {
    "operationId": "askHuman",
    "summary": "Ask your human to approve spending",
    "description": "Returns approve_url for your human to open. Poll GET /v1/handoffs/{id} until approved; a keyless request then returns a new api_key with the limit the human set. With a key, approval sets that key's new spending limit.",
    "security": [
     {},
     {
      "apiKey": []
     }
    ],
    "requestBody": {
     "required": false,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "reason": {
          "type": "string",
          "maxLength": 300
         },
         "number": {
          "type": "string"
         },
         "amount_cents": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100000
         }
        }
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "The approval request",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Handoff"
        }
       }
      }
     },
     "400": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/v1/handoffs/{id}": {
   "get": {
    "operationId": "getHandoff",
    "summary": "Check whether your human approved",
    "security": [
     {},
     {
      "apiKey": []
     }
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "token",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      },
      "description": "The ht_ token from POST /v1/handoffs"
     }
    ],
    "responses": {
     "200": {
      "description": "The approval request",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Handoff"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  }
 }
}
