Get started
Authentication
Both the PatientNow Essentials (PNE) and VISH APIs require two
things on every request: your gateway API key (an
apikey parameter) and HTTP Basic user credentials.
There are no anonymous endpoints.
Authentication is identical for PNE and VISH, and both share the same host
(api.envisiongo.com) — your gateway key determines which API your
account can reach. Send the apikey on every call, and identify the
user with Basic auth (header).
The auth scheme
Every request carries two credentials:
- An
apikey— your gateway key, identifying your integration to the API gateway. Send it on every call. - HTTP Basic user credentials — a username and password, Base64-encoded, identifying the acting user. The API validates them against an active user on each call; there is no login step or bearer token to exchange.
- Both are checked per request (the API is stateless).
- Authenticated calls run with that user's permissions.
- A missing/invalid
apikeyor bad user credentials return401 Unauthorized.
Auth puts your key and credentials on every request. Only call the API over
https:// so they are never sent in clear text. Use a dedicated API
user, not a real person's login, and rotate credentials if they are ever exposed.
Your gateway key (apikey)
The apikey is issued to your integration and is required on
every request, in addition to the Basic user credentials below. Pass it as
an apikey query-string parameter:
# apikey on the query string + Basic user credentials in the header:
curl "https://api.envisiongo.com/api/v1/status?apikey=YOUR_API_KEY" \
-u "USERNAME:PASSWORD"const token = btoa("USERNAME:PASSWORD"); // Node: Buffer.from(...).toString("base64")
const res = await fetch(`${base}/status?apikey=YOUR_API_KEY`, {
headers: { Authorization: `Basic ${token}` },
});from requests.auth import HTTPBasicAuth
res = requests.get(
f"{base}/status",
params={"apikey": "YOUR_API_KEY"},
auth=HTTPBasicAuth("USERNAME", "PASSWORD"),
)// Append apikey to the query string; Basic header set on the client (below).
var res = await http.GetAsync("status?apikey=YOUR_API_KEY");They are different things. The apikey identifies
your integration to the gateway; the Basic username/password identify the
user whose permissions the call runs under. You need both
— the apikey alone won't authenticate a user, and Basic auth alone
won't pass the gateway.
User credentials — Authorization header (recommended)
Send the Base64 of username:password in the standard Basic
Authorization header. Most HTTP clients build this for you when you
supply a username and password.
# Let cURL build the header (apikey still required on the query string):
curl "https://api.envisiongo.com/api/v1/status?apikey=YOUR_API_KEY" \
-u "USERNAME:PASSWORD"
# Equivalent explicit header:
curl "https://api.envisiongo.com/api/v1/status?apikey=YOUR_API_KEY" \
-H "Authorization: Basic $(printf 'USERNAME:PASSWORD' | base64)"const token = btoa("USERNAME:PASSWORD"); // Node: Buffer.from(...).toString("base64")
const res = await fetch(`${base}/status?apikey=YOUR_API_KEY`, {
headers: { Authorization: `Basic ${token}` },
});from requests.auth import HTTPBasicAuth
res = requests.get(
f"{base}/status",
params={"apikey": "YOUR_API_KEY"},
auth=HTTPBasicAuth("USERNAME", "PASSWORD"),
)var token = Convert.ToBase64String(Encoding.UTF8.GetBytes("USERNAME:PASSWORD"));
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", token);
var res = await http.GetAsync("status?apikey=YOUR_API_KEY");The Base64 value is the literal string username:password joined by
a single colon. The username itself must not contain a colon. Base64 is
encoding, not encryption — it is trivially reversible, which is exactly
why HTTPS is mandatory.
Header-less user token (api_key)
Where you genuinely can't set an Authorization header, the Base64
username:password token may instead be passed as an
api_key query parameter (note the underscore — this is
distinct from the gateway apikey above). Its value is identical to what
you'd put after Basic in the header. The gateway apikey
is still required alongside it.
curl "https://api.envisiongo.com/api/v1/status?apikey=YOUR_API_KEY&api_key=BASE64_OF_USER_COLON_PASS"Query strings are routinely written to server logs, proxy logs, and browser
history. Putting the user token there widens its exposure. Use
api_key only when headers are genuinely unavailable, and never in
URLs that end users can see.
Base URL
Both APIs share a single base URL — the host plus the versioned
api/v1 path:
https://api.envisiongo.com/api/v1So a typical full URL is
https://api.envisiongo.com/api/v1/customers. There is no per-customer
path prefix — your gateway apikey (not the URL) determines which API and
account a request resolves to.
| API | Base URL | First call to try |
|---|---|---|
| PatientNow Essentials (PNE) | https://api.envisiongo.com/api/v1 | GET /api/v1/status |
| VISH | https://api.envisiongo.com/api/v1 | GET /api/v1/companies |
Both APIs share the host api.envisiongo.com; your gateway
apikey determines which one your account reaches. VISH has no
status endpoint, so its cleanest connectivity check is
GET /api/v1/companies — see the
VISH quickstart.
Common 401 causes
A 401 Unauthorized means the request was rejected before your data
was touched. Work through these in order:
| Symptom | Likely cause | Fix |
|---|---|---|
| 401 on every call | Missing the gateway apikey, or missing the Authorization header | Send both — ?apikey=… on the URL and Basic credentials. Confirm the header isn't dropped on redirects. |
| 401 with a valid user, on every call | Wrong or unprovisioned apikey (e.g. used the underscore api_key token in place of the gateway key) | Use your gateway apikey (no underscore); confirm it's provisioned for the API you're calling. |
| 401 with a token you "know" is right | Encoded username : password with spaces, or wrong separator | Encode exactly username:password — one colon, no spaces. |
| 401 after it worked before | Password changed, or user deactivated | Re-issue credentials; the user must be active. |
| 401 only in the browser | Credentials not reaching the API across a redirect or CORS preflight | Call the canonical https URL directly; avoid http→https redirects. |
| Works in cURL, fails in code | Double-encoding (encoding an already-encoded token) | Base64 the raw user:pass once, not the header value. |
401 = not authenticated (bad/missing credentials). A request that authenticates but lacks permission, or asks for a record that isn't visible, may instead come back as 404 Not Found. If you get a 404 on a record you expect to exist, re-check the ID and that the authenticated user can see it.
Pre-flight checklist
- ✅ Calling over
https:// - ✅ Base URL ends in
/api/v1 - ✅ Gateway
apikey(no underscore) on the query string of every request - ✅
Authorization: Basic <base64(user:pass)>present on every request - ✅ Token is Base64 of
user:passwith a single colon, encoded once - ✅ The user is active and authorized for API access
- ✅ Using a dedicated API user, with the key and credentials kept out of source control