{
  "markdown": "# Free Public REST APIs - AI SENSE AS\n\nNo API key | No sign-up | No cost\n\nProvided by **[AI SENSE AS](https://aisenseapi.com)** (Oslo, Norway).\nFull endpoint reference: [`API.md`](API.md) | Repo: [github.com/aisenseapi/aisense-free-public-rest-apis](https://github.com/aisenseapi/aisense-free-public-rest-apis)\n\n**Base URL:** `https://aisenseapi.com/services/v1/`\n\n## Free public MCP endpoints\n\nAI agents can connect directly to 20 AI SENSE workflow tools at:\n\n`https://aisenseapi.com/mcp`\n\nThe AI SENSE MCP server covers Heartbeat, Lease, Agent Wake tasks, Agent\nInbox, human approval, webhook capture, temporary storage, URL shortening,\ntime and UUIDs. It needs no account or API key. Heartbeat uses\n`create_heartbeat`, `read_heartbeat` and `ping_heartbeat`. Lease uses\n`create_lease_namespace`, `acquire_lease`, `renew_lease`, `release_lease` and\n`complete_lease`. Agent Inbox uses `create_agent_inbox` and\n`read_agent_inbox`. See\n[`MCP.md`](MCP.md) for the tool list, data boundary and client examples.\n\nVerifyum has its own dedicated MCP endpoint at\n`https://api.verifyum.com/mcp`. It exposes the three Verifyum proof operations\nwithout an account or API key. File hashing still happens on the agent's\nmachine. The browser flow, public HTTP API and published protocol remain\navailable. The official MCP registry lists it as `com.verifyum/mcp` version\n`0.1.0`. Finalized proofs also join hourly and daily Merkle checkpoints in\nthe [Verifyum Witness Layer](https://verifyum.com/witness). Nine records\nsurround each finalized proof.\n\n| Tier | Records |\n| --- | --- |\n| Primary evidence | One finalized Solana Mainnet Memo transaction per proof |\n| Independent corroboration | Hourly OpenTimestamps on Bitcoin, daily qualified EU timestamp, daily witness-cosigned Sigsum and daily Certificate Transparency certificate |\n| Operator records and availability redundancy | Verifyum Ed25519 signature, GitHub checkpoint log, Software Heritage and Internet Archive |\n\nThe Solana transaction is the primary evidence. Deep Solana history generally\nrequires an archival provider. Glasklar, Mullvad and Tillitis cosign the\nSigsum digest with a quorum of two out of three. The qualified timestamp uses\nRFC 3161. Its eIDAS Article 41(2) presumption covers the daily checkpoint root\nalone. A Verifyum user proof is not a qualified electronic timestamp. Verifyum\nis not a qualified trust service. Software Heritage and Internet Archive show\nwhat was stored. They do not establish when the original file existed. The\nnumber of channels is not a quality score.\n\nEvery finalized proof is also announced on\n[Telegram](https://t.me/verifyum) and in the\n[Atom feed](https://verifyum.com/feed.xml). These are announcement channels.\nThey are excluded from the nine evidence records. Their timestamps date the\nannouncement. They say nothing about the original file date.\n\nAn agent can also assemble one decision record locally from its instructions,\nprompt, model, parameters, tool calls and output, then anchor only the\ncommitment. The proof shows that the exact record existed unchanged by the\nblock time. It does not prove that the model actually ran with the recorded\nsettings.\n\n---\n\n## Free public Agent2Agent (A2A) endpoint\n\nAgents that speak Agent2Agent can reach four of these capabilities at:\n\n`https://aisenseapi.com/a2a`\n\nJSON-RPC 2.0, protocol revision 1.0, no account and no API key. The agent card\nis a plain GET at `https://aisenseapi.com/.well-known/agent-card.json`.\n\nA2A is the protocol for delegating work to another agent. MCP is the protocol\nfor exposing tools. Most of this service is tools, so only the four task-shaped\ncapabilities are offered over A2A: `agent-wake`, `human-approval`,\n`agent-inbox` and `webhook-capture`. The other tools are not reachable through\nit, and MCP stays the richer surface with all twenty tools and their schemas.\n\nA2A puts no skill id on the wire, so the caller names the skill in a data part\nof the message, as `{\"skill\": \"agent-wake\", \"arguments\": { ... }}`. That is a\nconvention this service documents, not a field the protocol defines, and a\nmessage without it is refused. The card declares `streaming` and\n`pushNotifications` false, so those methods answer `-32004` and `-32003`.\n`ListTasks` returns an empty page, because nobody is authenticated and a task ID\nis the only credential there is. See [`API.md`](API.md#agent2agent-a2a) for the\nskills, task states, response shapes and error codes.\n\n---\n\n## SpeedUp (.su) - token cost, measured properly\n\nEvery serialization format marketed for LLM input ships a token-saving claim\nmeasured against a single tokenizer. Agent traffic crosses vendors, so we\nmeasured instead of assumed: six formats and 33 single-construct probes,\npriced by five vocabulary families (OpenAI o200k, DeepSeek, Qwen,\nSentencePiece, Tekken), with each provider's own token counter as ground\ntruth.\n\n- [`SU-PROFILE.md`](SU-PROFILE.md) - the SpeedUp profile: eight writing\n  conventions for agent-to-agent text, each citing its measured price tag\n- [`speedup/`](speedup/) - the measurement rig (Python, standard library\n  only), corpus, probes and raw numbers; rerun everything with your own keys\n- [The study](https://aisense.no/tokenizer-cost-study) - what survived\n  measurement, what did not, and why we decided against shipping yet another\n  format\n\nHeadline numbers: plain TSV averages 0.82x minified JSON across the\nfive-vocabulary union and beats the token-oriented formats on every model;\ndeclaring columns once and sending values positionally is the entire\nmechanism (minus 34 percent per key-value pair); base64 costs 3.9-4.6x the\nplaintext it encodes; and single-letter key dictionaries lose to full keys\non four of five vocabularies.\n\n---\n\n## Why this exists\n\nMost utility APIs require sign-up, rate limit tiers, or pricing for basic\noperations. This collection skips all of that. Drop a URL into curl, Python,\nJavaScript, or an LLM tool definition and it just works.\n\nThe collection covers two tiers of usefulness:\n\n- **Workflow endpoints** - the ones that solve real problems in pipelines and agent systems\n- **Standard utilities** - hashing, encoding, UUIDs, time, crypto - the building blocks\n\n---\n\n## Three things to know before you write a client\n\nThese are service-wide and they decide how your error handling has to look.\nEvery response shape in this repo was verified against production.\n\n**The response key is named after the endpoint.** `/md5_hash` returns\n`md5_hash`, `/random_color` returns `random_color`, `/ping` returns `ping`.\nThere is no generic `data` or `result` wrapper. Do not guess the key -\n[`API.md`](API.md) lists every one.\n\n**Errors are `{\"error\": \"message\"}` with a real HTTP status.** Uniform since\n2026-08-17: 400 is your mistake, 404 an unknown id or endpoint, 410 a capture,\naction or inbox that existed and has expired, 429 the rate limit, 500 our\nfailure, 502/504 an upstream. Branch on the status or on the `error` key - both\nare trustworthy, and every error body kept its exact wording through the\nchange, so older clients keep working.\n\n**There is a rate limit: 5000 requests per IP per 24 hours.** Exceeding it\nreturns HTTP 429 in the same flat error shape as everything else.\n\n---\n\n## The high-value endpoints\n\n### Heartbeat - know when a worker stops checking in\n\nCreate a monitor with an expected check-in interval, a grace period and one\naction for a missed deadline. The action can POST to a public webhook or wake\nan existing Agent Wake webhook task.\n\n```bash\ncurl -X POST https://aisenseapi.com/services/v1/heartbeat \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"expect_every_seconds\": 300,\n    \"grace_seconds\": 60,\n    \"on_miss\": {\n      \"url\": \"https://example.com/agent-offline\",\n      \"payload\": { \"agent\": \"worker-7\" }\n    }\n  }'\n```\n\nThe response gives you an unguessable `heartbeat_id`, `ping_url` and\n`status_url`. Call the ping URL with POST after each successful cycle.\nEach ping moves the expected deadline. It does not move the fixed 24-hour\nexpiry. A missed deadline fires once, with no retry.\n\nMCP clients can use `create_heartbeat`, `read_heartbeat` and\n`ping_heartbeat` for the same state.\n\nWebhook destinations are checked for SSRF at creation and delivery. Private\nand reserved addresses, URL credentials, fragments and redirects are blocked.\nSee [`API.md`](API.md) for the states and response fields.\n\n---\n\n### Lease - one winner for shared agent work\n\nLease coordinates workers without an account. Mint a private namespace, then\nclaim a key for a short period:\n\n```bash\ncurl -X POST https://aisenseapi.com/services/v1/lease/namespace \\\n  -H \"Content-Type: application/json\" -d '{}'\n\ncurl -X POST https://aisenseapi.com/services/v1/lease \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"namespace\": \"ns_...\",\n    \"key\": \"invoice:2026-09-05\",\n    \"ttl_seconds\": 60,\n    \"fingerprint\": \"charge-order-501\"\n  }'\n```\n\nThe winner receives an `owner_token` and a monotonic `fencing_token`. A second\nworker receives HTTP 409 while the lease is held. The owner can renew, release\nor complete the lease with a JSON result. Later callers with the same key and\nfingerprint can reuse that completed result.\n\nThe lease has a fixed absolute expiry 24 hours after its first acquisition.\nRenewals cannot extend it. Raw keys, namespaces, owner tokens and fingerprints\nare not stored. See [`API.md`](API.md) for the full acquire and completion\nflow.\n\nThe matching MCP tools are `create_lease_namespace`, `acquire_lease`,\n`renew_lease`, `release_lease` and `complete_lease`.\n\n---\n\n### Agent Wake - resume after an outside event\n\nCreate one task that waits for a webhook, a human answer or a chosen time. MCP\nclients use the current Tasks extension and poll `tasks/get`. REST clients use\n`POST /agent_wake` and the returned status URL. A2A clients name the\n`agent-wake` skill and poll `GetTask`, which is the one skill that answers with\nan A2A Task rather than a Message.\n\n```json\n{ \"event_type\": \"webhook\", \"timeout_seconds\": 3600 }\n```\n\nThe result contains an unguessable task ID and a wake URL. The first request to\nthat URL completes the task. Human tasks create a hosted form. Time tasks\ncomplete on the first read after the selected timestamp. Each task expires in\n60 seconds to 24 hours.\n\nREST clients can wait for a terminal state with\n`GET /agent_wake/{task_id}/wait/{seconds}`. The final value accepts 0 to 25.\n\nSee [`MCP.md`](MCP.md) for the task flow, and [`API.md`](API.md) for the REST\ncalls and the [A2A skill](API.md#agent2agent-a2a).\n\n---\n\n### Webhook Action - human-in-the-loop for agents\n\nThe standout endpoint for AI and automation work. When an automated pipeline\nneeds a human decision before continuing, this handles the whole pattern with\nzero backend setup.\n\n**How it works:**\n\n1. `POST` a form definition (radio buttons, dropdowns, text fields, checkboxes)\n2. Get back a `form_url`, `result_url` and `wait_url`\n3. Send the `form_url` to a human via email or Slack\n4. Read `result_url`, or use `wait_url` to wait up to 25 seconds\n\n```bash\ncurl -X POST https://aisenseapi.com/services/v1/webhook_action \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"title\": \"Approve deployment to production?\",\n    \"fields\": [\n      {\n        \"type\": \"radio\",\n        \"name\": \"decision\",\n        \"label\": \"Decision\",\n        \"required\": true,\n        \"options\": [\n          { \"value\": \"approve\", \"label\": \"Approve\" },\n          { \"value\": \"reject\", \"label\": \"Reject\" }\n        ]\n      },\n      { \"type\": \"textarea\", \"name\": \"comment\", \"label\": \"Notes (optional)\" }\n    ]\n  }'\n```\n\n```json\n{\n  \"ok\": true,\n  \"action_id\": \"9e0e6d3b-1a45-44c5-9e0b-92f5f3bdb2f1\",\n  \"form_url\": \"https://aisenseapi.com/services/v1/webhook_action/9e0e6d3b-.../form\",\n  \"result_url\": \"https://aisenseapi.com/services/v1/webhook_action/9e0e6d3b-...\",\n  \"wait_url\": \"https://aisenseapi.com/services/v1/webhook_action/9e0e6d3b-.../wait/25\",\n  \"expire_timestamp\": 1786959912,\n  \"expire_datetime\": \"2026-08-17T09:45:12Z\"\n}\n```\n\nPoll for the answer:\n\n```bash\ncurl https://aisenseapi.com/services/v1/webhook_action/{action_id}\n# \"status\": \"pending\" -> \"answered\", with the submission under \"response\"\n```\n\nField types: `radio`, `select`, `text`, `textarea`, `checkbox`. `options`\naccepts plain strings or `{\"value\": ..., \"label\": ...}` objects. Expires after\n24 hours.\n\nAdd `respondents` from 2 to 20 for separate one-use form links. The result then\nmoves through `pending`, `partial` and `answered`, with answer counts, a tally\nand individual responses. Add `notify_url` when you want one completion signal\nthat points back to the result without copying the answers.\n\nMCP clients use `create_human_approval` and `read_human_approval`. A2A clients\nname the `human-approval` skill, which creates the form and returns its URLs;\nreading the answer stays on REST or MCP.\n\n---\n\n### Webhook Capture - inspect any inbound HTTP request\n\nCreate a capture, get a unique URL, point any external service at it\n(Stripe, GitHub, Shopify), and read back the full request - method, headers,\nquery parameters, IP, and parsed body. No ngrok, no local tunnel, no server.\n\n```bash\n# 1. Create a capture\ncurl -X POST https://aisenseapi.com/services/v1/webhook_capture\n# -> { \"status\": \"pending\", \"capture_id\": \"...\", \"update_url\": \"...\", \"read_url\": \"...\", \"wait_url\": \"...\" }\n\n# 2. Point your webhook sender at update_url, with any HTTP method\ncurl -X POST {update_url} -H \"Content-Type: application/json\" -d '{\"event\":\"payment.created\"}'\n\n# 3. Wait up to 25 seconds for the first request\ncurl https://aisenseapi.com/services/v1/webhook_capture/{capture_id}/wait/25\n```\n\n```json\n{\n  \"ok\": true,\n  \"capture_id\": \"6f8c9e52-...\",\n  \"captured_at_timestamp\": 1786873316,\n  \"captured_at_datetime\": \"2026-08-16T09:41:56Z\",\n  \"request\": {\n    \"method\": \"POST\",\n    \"uri\": \"/services/v1/webhook_capture/6f8c9e52-.../update\",\n    \"headers\": { \"content-type\": \"application/json\" },\n    \"client_ip\": \"203.0.113.10\",\n    \"body\": { \"json\": { \"event\": \"payment.created\" }, \"text\": null, \"base64\": null, \"raw_length\": 28 }\n  }\n}\n```\n\nExpires after 24 hours.\n\nThe first inbound request wins and later retries cannot replace it. Captured\nbodies are capped at 256 KB. The create body may contain `notify_url` for one\ncompletion signal.\n\nMCP clients use `create_webhook_capture` and `read_webhook_capture`. A2A clients\nname the `webhook-capture` skill, which creates the capture and returns its URLs;\nreading the request stays on REST or MCP.\n\n---\n\n### Agent Inbox - a disposable mail address the agent controls\n\nFor the step where something has to arrive by email: a verification code, a\nconfirmation link, a sign-up mail. Create an inbox, hand out the address, read\nthe mail back as cleaned text. No account, no API key, and it lasts at most 24\nhours.\n\n```bash\ncurl -X POST https://aisenseapi.com/services/v1/inbox\n```\n\n```json\n{\n  \"ok\": true,\n  \"inbox_id\": \"a85d0bee-f8f7-4be1-a1b3-8d58f3dbdfc7\",\n  \"slug\": \"ztjqt7n\",\n  \"address\": \"aisense+ztjqt7n@aisenseapi.com\",\n  \"read_url\": \"https://aisenseapi.com/services/v1/inbox/a85d0bee-f8f7-4be1-a1b3-8d58f3dbdfc7\",\n  \"wait_url\": \"https://aisenseapi.com/services/v1/inbox/a85d0bee-f8f7-4be1-a1b3-8d58f3dbdfc7/wait/25\",\n  \"expire_timestamp\": 1800086400\n}\n```\n\n**Two identifiers come back, and they are not interchangeable.** The `slug` is\nthe seven characters inside the address. It is public by construction: it\ntravels in mail headers, bounces and sender logs. Knowing it lets anyone send\nmail to the inbox. It never lets anyone read the inbox, and it never appears\nin a URL. The `inbox_id` is a UUID and the only credential that reads. Anyone\nholding it reads the mail, and it is returned once, at creation. Guessing the\naddress does not read the inbox. A wrong `inbox_id` and a missing inbox both\nanswer 404, never 403, so the two are indistinguishable.\n\nRead the mail, or wait up to 25 seconds for it:\n\n```bash\ncurl https://aisenseapi.com/services/v1/inbox/{inbox_id}\ncurl https://aisenseapi.com/services/v1/inbox/{inbox_id}/wait/25\n```\n\n```json\n{\n  \"ok\": true,\n  \"slug\": \"ztjqt7n\",\n  \"address\": \"aisense+ztjqt7n@aisenseapi.com\",\n  \"received\": 1,\n  \"truncated\": false,\n  \"messages\": [\n    {\n      \"from\": \"noreply@example.com\",\n      \"subject\": \"Your verification code\",\n      \"date\": \"2027-01-15T08:00:00Z\",\n      \"text\": \"Your code is 481516. Confirm at https://example.com/confirm/abc\",\n      \"codes\": [ \"481516\" ],\n      \"links\": [ \"https://example.com/confirm/abc\" ]\n    }\n  ],\n  \"created_at_timestamp\": 1800000000,\n  \"expire_timestamp\": 1800086400\n}\n```\n\nThe read response does not contain `inbox_id`. The credential is never echoed\nback. The wait form adds `waited_seconds` and `wait_reason` to the same object.\nA value above 25 is clamped to 25, the same as every other wait route.\n\n`codes` are standalone 4 to 8 digit numbers. `links` are public http(s) links\nonly; private-IP and localhost links are dropped. `date` is the time the\nservice received the message, not the sender's `Date` header, because that\nheader is sender controlled.\n\n`truncated` says a message was refused, whether the inbox hit the message\ncount or the total size. A full inbox refuses new mail rather than\nevicting old mail, so without the flag an agent waiting for a code would see a\nfull inbox, no code and no reason. The wait watches the flag as well as the\ncount, so a refusal ends it instead of leaving the caller to time out.\n\nAttachments, raw MIME, arbitrary headers, scripts, styles, private-IP links and\nlocalhost links are stripped before storage. Only the sender address, subject,\nreceived time, cleaned text, codes and public links are kept.\n\nLimits: 20 messages per inbox, 64 KiB of cleaned text per message, 256 KiB per\ninbox in total, 50 inboxes per client per UTC day and 5000 active inboxes\nservice wide. The 24-hour lifetime is fixed and cannot be extended.\n\nMCP clients use `create_agent_inbox` and `read_agent_inbox`, whose wait watches\n`truncated` as well and returns as soon as the cap refuses a message. A2A\nclients name the `agent-inbox` skill, which creates the inbox and returns its\naddress and URLs; reading the mail stays on REST or MCP.\n\n---\n\n### Storage - ephemeral key-value store for pipelines\n\nPost any JSON, text, or file. Get back a UUID. Retrieve it from anywhere -\nanother machine, a different agent call, a downstream pipeline step.\n\n**The body is stored verbatim.** Whatever you send is exactly what comes back;\nno wrapper is added or removed.\n\n```bash\ncurl -X POST https://aisenseapi.com/services/v1/storage \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"result\": 42, \"status\": \"complete\"}'\n# -> { \"storage_id\": \"550e8400-e29b-41d4-a716-446655440000\", \"expire_timestamp\": 1738457158 }\n\ncurl https://aisenseapi.com/services/v1/storage/550e8400-e29b-41d4-a716-446655440000\n# -> {\"result\": 42, \"status\": \"complete\"}\n```\n\nExpires after 24 hours.\n\n---\n\n### URL Shortener\n\n```bash\ncurl \"https://aisenseapi.com/services/v1/url_shortener/https://example.com/very/long/path\"\n# -> { \"short_url\": \"https://307.fi/KtNshX2B\", \"expire_timestamp\": 1786959715 }\n```\n\nExpires after 24 hours.\n\n---\n\n### IP Reverse Lookup\n\n```bash\ncurl https://aisenseapi.com/services/v1/ip_reverse_lookup/8.8.8.8\n```\n\n```json\n{\n  \"ip\": \"8.8.8.8\",\n  \"country\": \"United States\",\n  \"city\": null,\n  \"location\": { \"lat\": \"37.751000\", \"lng\": \"-97.822000\" },\n  \"place\": null,\n  \"timezone\": \"America/Chicago\"\n}\n```\n\n`city` and `place` are frequently `null`, and the coordinates fall back to the\ncountry centroid when the city is unknown. Also available: resolve a domain to\nits IP.\n\n```bash\ncurl https://aisenseapi.com/services/v1/domain_ip_lookup/example.com\n# -> { \"domain\": \"example.com\", \"ip\": \"104.20.23.154\" }\n```\n\n---\n\n## Standard utilities\n\n### Hashing - MD5, SHA1, SHA256, SHA512, CRC32\n\nAccepts JSON, plain text (`Content-Type: text/plain`), or a file upload.\n**Each returns a key named after the algorithm, not `hash`.**\n\n```bash\ncurl -X POST https://aisenseapi.com/services/v1/sha256_hash \\\n  -H \"Content-Type: application/json\" -d '{\"data\": \"Hello\"}'\n# -> { \"sha256_hash\": \"185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969\" }\n```\n\n`md5_hash` | `sha1_hash` | `sha256_hash` | `sha512_hash` | `crc32_checksum`\n\n`crc32_checksum` returns an integer, not a hex string.\n\n---\n\n### Encoding - Base64, Base58, Base32, JWT, QR Code\n\n```bash\n# Encode\ncurl -X POST https://aisenseapi.com/services/v1/base64_encode \\\n  -H \"Content-Type: application/json\" -d '{\"data\": \"Hello world\"}'\n# -> { \"base64_encoded_data\": \"SGVsbG8gd29ybGQ=\" }\n\n# Decode - returns the raw bytes, not JSON\ncurl -X POST https://aisenseapi.com/services/v1/base64_decode \\\n  -H \"Content-Type: application/json\" -d '{\"data\": \"SGVsbG8gd29ybGQ=\"}'\n# -> Hello world\n\n# ...unless you ask for JSON\ncurl -X POST https://aisenseapi.com/services/v1/base64_decode \\\n  -H \"Content-Type: application/json\" -H \"Accept: application/json\" \\\n  -d '{\"data\": \"eyJrZXkiOiJ2YWx1ZSJ9\"}'\n# -> { \"type\": \"json\", \"decoded_data\": { \"key\": \"value\" } }\n```\n\nThe three decoders (`base64_decode`, `base58_decode`, `base32_decode`) answer\nwith `application/octet-stream` unless you send `Accept: application/json`.\nThis is the one place the API is not JSON.\n\n**JWT - `data` takes the claims as a JSON object, or as a string containing\nJSON.** Both forms produce the same token.\n\n```bash\ncurl -X POST https://aisenseapi.com/services/v1/jwt_encode \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"data\": {\"user\": \"alice\"}, \"secret\": \"my-secret-key\"}'\n# -> { \"jwt\": \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...\" }\n```\n\n`jwt_decode` returns `decoded_payload`.\n\n**QR - the request field is `payload`, with `data` accepted as an alias.**\n\n```bash\ncurl -X POST https://aisenseapi.com/services/v1/qrcode_encode \\\n  -H \"Content-Type: application/json\" -d '{\"payload\": \"https://example.com\"}'\n# -> { \"qrcode_image\": \"iVBORw0KGgoAAAANSUhEUgAA...\", \"image_type\": \"png\" }\n```\n\n`qrcode_decode` takes the same `payload` field (or a file upload) and returns\n`qrcode_content`.\n\n---\n\n### Random - UUID, GUID, number, color, password\n\n```bash\ncurl https://aisenseapi.com/services/v1/uuid            # { \"uuid\": \"...\" }\ncurl https://aisenseapi.com/services/v1/guid            # { \"guid\": \"...\" }\ncurl https://aisenseapi.com/services/v1/random_color    # { \"random_color\": \"#9b6bbf\" }\ncurl https://aisenseapi.com/services/v1/random_number/1/100\n# -> { \"random_number\": 73, \"range\": { \"from\": 1, \"to\": 100 } }\ncurl https://aisenseapi.com/services/v1/password/16\n# -> { \"password\": \"jFehS]AKGx9wl[jp\", \"password_length\": 16 }\n```\n\nA single argument to `random_number` is the upper bound, with the lower bound\nfixed at 1.\n\n---\n\n### Time - Datetime, Timestamp, Timezones\n\n```bash\ncurl https://aisenseapi.com/services/v1/datetime            # UTC\ncurl https://aisenseapi.com/services/v1/datetime/+0200      # with offset\ncurl https://aisenseapi.com/services/v1/timestamp\ncurl https://aisenseapi.com/services/v1/microtimestamp\ncurl https://aisenseapi.com/services/v1/timezones\ncurl https://aisenseapi.com/services/v1/swatchinternettime\n```\n\nThe offset must be **four digits** with an optional sign - `+0200`, `-0530`,\n`0100`. An hour-only value like `1` is not a valid route.\n\n`/timezones` returns objects, not strings:\n`{\"timezones\": [{\"timezone\": \"Europe/Oslo\", \"offset\": \"+0200\"}, ...]}`.\n\n---\n\n### Web utilities - Ping, Health, Client IP, User Agent\n\n```bash\ncurl https://aisenseapi.com/services/v1/ping        # { \"ping\": \"pong\" }\ncurl https://aisenseapi.com/services/v1/health      # { \"status\": \"ok\", \"microtimestamp\": ... }\ncurl https://aisenseapi.com/services/v1/client_ip   # { \"ip\": \"203.0.113.42\" }\ncurl https://aisenseapi.com/services/v1/user_agent  # { \"user_agent\": \"curl/8.5.0\" }\n```\n\n---\n\n### Crypto - Wallet generation and balance lookup\n\n```bash\ncurl https://aisenseapi.com/services/v1/solana/generate_new_wallet\ncurl https://aisenseapi.com/services/v1/bitcoin/generate_new_wallet\ncurl https://aisenseapi.com/services/v1/ethereum/generate_new_wallet\n\ncurl https://aisenseapi.com/services/v1/solana/balance/{address}\ncurl https://aisenseapi.com/services/v1/bitcoin/balance/{address}\ncurl https://aisenseapi.com/services/v1/ethereum/balance/{address}\n```\n\nAll three generators return `public_address` (Bitcoin also returns\n`private_key_wif`). Ethereum balances come back as **strings** -\n`{\"wallet\": \"0x...\", \"balance_eth\": \"6.634527787345637061\", \"balance_wei\": \"6634527787345637061\"}`\n- because Wei routinely exceeds `2^53`, the largest integer a JSON number\nsurvives in a JavaScript client.\n\n> Wallet generation is for development and testing only. A key produced by a\n> public HTTP endpoint has crossed a network you do not control. Never fund one.\n\n---\n\n## Quick start by language\n\n**curl**\n```bash\ncurl https://aisenseapi.com/services/v1/uuid\n```\n\n**Python** - zero dependencies, standard library only.\n```python\nfrom aisense_api import AISenseAPI\napi = AISenseAPI()\n\nprint(api.get_uuid()[\"uuid\"])\nprint(api.hash_sha256(\"Hello\")[\"sha256_hash\"])\nprint(api.ip_reverse_lookup(\"8.8.8.8\")[\"country\"])\n```\n\n**JavaScript** - Node 18+ or any modern browser, native fetch.\n```javascript\nimport { AISenseAPI } from './aisense-api.js'\nconst api = new AISenseAPI()\n\nconsole.log((await api.getUUID()).uuid)\nconsole.log((await api.hashSHA256('Hello')).sha256_hash)\nconsole.log((await api.ipReverseLookup('8.8.8.8')).country)\n```\n\nBoth clients return the parsed response, and every method's docstring names the\nexact response key. They also raise a clear error when a path does not exist,\nrather than letting the debug echo surface as a JSON parse failure.\n\n**LLM function calling (OpenAI, Gemini, Mistral, ...)**\n```python\nimport json\nfrom openai import OpenAI\n\nwith open(\"openai-tools.json\") as f:\n    tools = json.load(f)\n\nclient = OpenAI()\nresponse = client.chat.completions.create(\n    model=\"gpt-4o\",\n    tools=tools,\n    messages=[{\"role\": \"user\", \"content\": \"Generate a UUID and hash the word Hello with SHA256\"}]\n)\n```\n\n**Claude** - [`SKILL.md`](SKILL.md) is included. Add it to Claude's context and\nit will use these APIs as tools automatically.\n\n---\n\n## What's in the repo\n\n| File | Purpose |\n|------|---------|\n| [`API.md`](API.md) | Full endpoint reference - the verified source of truth |\n| [`MCP.md`](MCP.md) | Remote MCP server, tool list and client examples |\n| [`server.json`](server.json) | Metadata for the official MCP Registry |\n| [`aisense_api.py`](aisense_api.py) | Python client (standard library only) |\n| [`aisense-api.js`](aisense-api.js) | JavaScript ESM client |\n| [`openai-tools.json`](openai-tools.json) | Tool definitions for any LLM with function calling |\n| [`SKILL.md`](SKILL.md) | Claude skill file |\n| [`test.sh`](test.sh) | Asserts on response bodies and statuses; exits `1` on failure (CI-friendly) |\n| [`tools/check-text.php`](tools/check-text.php) | Checks documentation punctuation before commit |\n\n`test.sh` asserts on response bodies as well as status codes. Bodies are the\npart that matters most: a status-code-only suite passes an endpoint that\nanswers 200 with the wrong response key.\n\n---\n\n## Endpoint summary\n\nAll paths are relative to `https://aisenseapi.com/services/v1/`\n\n| Category | Endpoint | Method | Response key(s) |\n|----------|----------|--------|-----------------|\n| Time | `/datetime[/{offset}]` | GET | `datetime` |\n| Time | `/timestamp` | GET | `timestamp` |\n| Time | `/microtimestamp` | GET | `microtimestamp` |\n| Time | `/timezones[/{offset}]` | GET | `timezones` |\n| Time | `/swatchinternettime` | GET | `beat`, `date` |\n| Time | `/timestamp_convert` | POST | `input`, `detected`, `timestamp`, `datetime`, `rfc2822`, `utc_datetime` |\n| Random | `/random_number[/{from}[/{to}]]` | GET | `random_number`, `range` |\n| Random | `/random_color` | GET | `random_color` |\n| Random | `/uuid` | GET | `uuid` |\n| Random | `/guid` | GET | `guid` |\n| Random | `/password[/{length}]` | GET | `password`, `password_length` |\n| Transform | `/base64_encode` | POST | `base64_encoded_data` |\n| Transform | `/base64_decode` | POST | raw bytes, or `type` + `decoded_data` |\n| Transform | `/base58_encode` | POST | `base58_encoded_data` |\n| Transform | `/base58_decode` | POST | raw bytes, or `type` + `decoded_data` |\n| Transform | `/base32_encode` | POST | `base32_encoded_data` |\n| Transform | `/base32_decode` | POST | raw bytes, or `type` + `decoded_data` |\n| Transform | `/slugify` | POST | `slug` |\n| Transform | `/jwt_encode` | POST | `jwt` |\n| Transform | `/jwt_decode` | POST | `decoded_payload` |\n| Transform | `/qrcode_encode` | POST | `qrcode_image`, `image_type` |\n| Transform | `/qrcode_decode` | POST | `qrcode_content` |\n| Hash | `/md5_hash` | POST | `md5_hash` |\n| Hash | `/sha1_hash` | POST | `sha1_hash` |\n| Hash | `/sha256_hash` | POST | `sha256_hash` |\n| Hash | `/sha512_hash` | POST | `sha512_hash` |\n| Hash | `/crc32_checksum` | POST | `crc32_checksum` |\n| Hash | `/hash_verify` | POST | `match`, `algorithm`, `computed` |\n| Web | `/ping` | GET | `ping` |\n| Web | `/health` | GET | `status`, `microtimestamp` |\n| Web | `/client_ip` | GET | `ip` |\n| Web | `/html2pdf` | POST | `storage_id`, `storage_url`, `expire_timestamp` |\n| Web | `/user_agent` | GET | `user_agent` |\n| Web | `/ip_reverse_lookup/{ip}` | GET | `ip`, `country`, `city`, `location`, `place`, `timezone` |\n| Web | `/domain_ip_lookup/{domain}` | GET | `domain`, `ip` |\n| Web | `/email_validate` | POST | `email`, `valid_syntax`, `domain`, `has_mx`, `mx_hosts` |\n| Web | `/storage` | POST / GET | `storage_id`, `expire_timestamp` |\n| Web | `/url_shortener/{url}` | GET | `short_url`, `expire_timestamp` |\n| Web | `/webhook_capture` | POST / GET | `capture_id`, `update_url`, `read_url`, `wait_url` |\n| Web | `/webhook_action` | POST / GET | `action_id`, form URL or URLs, `result_url`, `wait_url` |\n| Web | `/webhook_schedule` | POST / GET / DELETE | one-shot or recurring status, counts and result |\n| Web | `/agent_wake` | POST / GET / DELETE | `taskId`, `status`, `result`, wait support |\n| Web | `/inbox` | POST | `inbox_id`, `slug`, `address`, `read_url`, `wait_url`, `expire_timestamp` |\n| Web | `/inbox/{inbox_id}` | GET | `slug`, `address`, `received`, `truncated`, `messages`, timing fields |\n| Web | `/heartbeat` | POST | `heartbeat_id`, `status`, timing fields, `ping_url`, `status_url` |\n| Web | `/heartbeat/{id}` | GET | status, timing fields, counters, optional `delivery` |\n| Web | `/heartbeat/{id}/ping` | POST | updated timing fields and counters |\n| Web | `/lease/namespace` | POST | `namespace`, `entropy_bits` |\n| Web | `/lease`, `/lease/acquire` | POST | status, owner and fencing tokens, expiry fields, optional result |\n| Web | `/lease/renew`, `/lease/release`, `/lease/complete` | POST | status, fencing token, expiry fields, optional result |\n| Web | `/validate/{type}` | POST | `type`, `valid`, per-check fields |\n| Crypto | `/solana/generate_new_wallet` | GET | `private_key`, `public_address` |\n| Crypto | `/solana/balance/{address}` | GET | `wallet`, `balance_sol`, `balance_lamports` |\n| Crypto | `/bitcoin/generate_new_wallet` | GET | `private_key`, `private_key_wif`, `public_address` |\n| Crypto | `/bitcoin/balance/{address}` | GET | `wallet`, `final_balance_btc`, `final_balance_sats` |\n| Crypto | `/ethereum/generate_new_wallet` | GET | `private_key`, `public_address` |\n| Crypto | `/ethereum/balance/{address}` | GET | `wallet`, `balance_eth`, `balance_wei` |\n\n---\n\n## Notes\n\n- POST endpoints accept JSON, plain text (`Content-Type: text/plain`), or file uploads\n- Storage, URL Shortener, Webhook Capture, Webhook Action, Webhook Schedule, Agent Wake, Agent Inbox, Heartbeat and Lease have a 24-hour active lifetime or absolute lifecycle\n- Heartbeat terminal state can remain readable for another 24 hours after it fires, misses or expires\n- `Access-Control-Allow-Origin: *` is set on every response, so these are callable from a browser\n- Rate limit: 5000 requests per IP per 24 hours\n\n---\n\n**AI SENSE AS** | [aisenseapi.com](https://aisenseapi.com)\nPostboks 1202 Vika, 0110 Oslo, Norway\n\nMIT License\n",
  "bytes": 31916,
  "sha": "f682056483b5fe42bed2ae9723a248dbbfdc7bafa2d0554674208920e13a687e",
  "repo_slug": "aisenseapi/aisense-free-public-rest-apis",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_com_aisenseapi_free_public_tools_d67e383f/readme"
}