set -eu
umask 077
# Path values must be URL-encoded; query string excludes the leading question mark.
url="${HD_BASE_URL:?Set API origin}/v1/users/journal/injections/${HD_QUERY_STRING:+?${HD_QUERY_STRING}}"
printf 'X-Brand-Slug: hi-doctor\nAccept: application/json\n' > "${HD_REQUEST_HEADERS_FILE:?Private header file}"
printf 'Authorization: Bearer %s\n' "${HD_ACCESS_TOKEN:?Set backend JWT}" >> "$HD_REQUEST_HEADERS_FILE"
curl --silent --show-error --max-time 30 --request POST \
--header "@$HD_REQUEST_HEADERS_FILE" \
--dump-header "${HD_HEADERS_FILE:?Private response header file}" \
--output "${HD_RESPONSE_FILE:?Private response file}" \
--write-out '%{http_code}\n%{content_type}\n' \
--header 'Content-Type: application/json' \
--data-binary "@${HD_REQUEST_FILE:?JSON fixture file}" \
"$url"import os, json
from pathlib import Path
from urllib.parse import quote
import requests
os.umask(0o077)
url = os.environ["HD_BASE_URL"].rstrip("/") + '/v1/users/journal/injections/'
if os.environ.get("HD_QUERY_STRING"): url += "?" + os.environ["HD_QUERY_STRING"]
headers = {"X-Brand-Slug": "hi-doctor", "Accept": 'application/json'}
headers["Authorization"] = "Bearer " + os.environ["HD_ACCESS_TOKEN"]
kwargs = {}
kwargs["json"] = json.loads(Path(os.environ["HD_REQUEST_FILE"]).read_text())
response = requests.request('POST', url, headers=headers, timeout=30, allow_redirects=False, **kwargs)
Path(os.environ["HD_RESPONSE_FILE"]).write_bytes(response.content)
Path(os.environ["HD_HEADERS_FILE"]).write_text(json.dumps(dict(response.headers)))
print(response.status_code)
print(response.headers.get("Content-Type", ""))
import { readFileSync, writeFileSync } from "node:fs";
const env = process.env;
let url = env.HD_BASE_URL.replace(/\/$/, "") + "/v1/users/journal/injections/";
if (env.HD_QUERY_STRING) url += "?" + env.HD_QUERY_STRING;
const headers = { "X-Brand-Slug": "hi-doctor", "Accept": "application/json" };
headers.Authorization = "Bearer " + env.HD_ACCESS_TOKEN;
const options = { method: "POST", headers, redirect: "manual", signal: AbortSignal.timeout(30000) };
headers["Content-Type"] = "application/json";
options.body = readFileSync(env.HD_REQUEST_FILE, "utf8");
const response = await fetch(url, options);
writeFileSync(env.HD_RESPONSE_FILE, Buffer.from(await response.arrayBuffer()), {mode: 0o600});
writeFileSync(env.HD_HEADERS_FILE, JSON.stringify(Object.fromEntries(response.headers)), {mode: 0o600});
console.log(response.status);
console.log(response.headers.get("content-type") ?? "");
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hi-doctor.ai/v1/users/journal/injections/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'medication' => 'Synthetic example',
'dose' => 'TEST',
'injected_at' => '2026-10-04T12:00:00Z',
'injection_site' => 'abdomen',
'note' => 'Synthetic example'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.hi-doctor.ai/v1/users/journal/injections/"
payload := strings.NewReader("{\n \"medication\": \"Synthetic example\",\n \"dose\": \"TEST\",\n \"injected_at\": \"2026-10-04T12:00:00Z\",\n \"injection_site\": \"abdomen\",\n \"note\": \"Synthetic example\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.hi-doctor.ai/v1/users/journal/injections/")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"medication\": \"Synthetic example\",\n \"dose\": \"TEST\",\n \"injected_at\": \"2026-10-04T12:00:00Z\",\n \"injection_site\": \"abdomen\",\n \"note\": \"Synthetic example\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hi-doctor.ai/v1/users/journal/injections/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"medication\": \"Synthetic example\",\n \"dose\": \"TEST\",\n \"injected_at\": \"2026-10-04T12:00:00Z\",\n \"injection_site\": \"abdomen\",\n \"note\": \"Synthetic example\"\n}"
response = http.request(request)
puts response.read_body{
"id": "3185a308-a283-5b1f-b5fa-174a58ab8491",
"created_at": "2026-10-05T17:48:32.374222Z",
"updated_at": "2026-10-05T17:48:32.374236Z",
"medication": "Synthetic example",
"dose": "TEST",
"injected_at": "2026-10-04T12:00:00Z",
"injection_site": "abdomen",
"note": "Synthetic example"
}Create an injection entry
Appends — unlike weight, every call creates a separate entry, including for the same day. injected_at is required and must carry its UTC offset.
Access, effects and retries
Ownership: Patient own row; user/brand server-assigned.
Prerequisites: An authenticated patient account is required.
Effects: Appends new entry.
Retries: Repeat can create duplicate entry; no idempotency key.
set -eu
umask 077
# Path values must be URL-encoded; query string excludes the leading question mark.
url="${HD_BASE_URL:?Set API origin}/v1/users/journal/injections/${HD_QUERY_STRING:+?${HD_QUERY_STRING}}"
printf 'X-Brand-Slug: hi-doctor\nAccept: application/json\n' > "${HD_REQUEST_HEADERS_FILE:?Private header file}"
printf 'Authorization: Bearer %s\n' "${HD_ACCESS_TOKEN:?Set backend JWT}" >> "$HD_REQUEST_HEADERS_FILE"
curl --silent --show-error --max-time 30 --request POST \
--header "@$HD_REQUEST_HEADERS_FILE" \
--dump-header "${HD_HEADERS_FILE:?Private response header file}" \
--output "${HD_RESPONSE_FILE:?Private response file}" \
--write-out '%{http_code}\n%{content_type}\n' \
--header 'Content-Type: application/json' \
--data-binary "@${HD_REQUEST_FILE:?JSON fixture file}" \
"$url"import os, json
from pathlib import Path
from urllib.parse import quote
import requests
os.umask(0o077)
url = os.environ["HD_BASE_URL"].rstrip("/") + '/v1/users/journal/injections/'
if os.environ.get("HD_QUERY_STRING"): url += "?" + os.environ["HD_QUERY_STRING"]
headers = {"X-Brand-Slug": "hi-doctor", "Accept": 'application/json'}
headers["Authorization"] = "Bearer " + os.environ["HD_ACCESS_TOKEN"]
kwargs = {}
kwargs["json"] = json.loads(Path(os.environ["HD_REQUEST_FILE"]).read_text())
response = requests.request('POST', url, headers=headers, timeout=30, allow_redirects=False, **kwargs)
Path(os.environ["HD_RESPONSE_FILE"]).write_bytes(response.content)
Path(os.environ["HD_HEADERS_FILE"]).write_text(json.dumps(dict(response.headers)))
print(response.status_code)
print(response.headers.get("Content-Type", ""))
import { readFileSync, writeFileSync } from "node:fs";
const env = process.env;
let url = env.HD_BASE_URL.replace(/\/$/, "") + "/v1/users/journal/injections/";
if (env.HD_QUERY_STRING) url += "?" + env.HD_QUERY_STRING;
const headers = { "X-Brand-Slug": "hi-doctor", "Accept": "application/json" };
headers.Authorization = "Bearer " + env.HD_ACCESS_TOKEN;
const options = { method: "POST", headers, redirect: "manual", signal: AbortSignal.timeout(30000) };
headers["Content-Type"] = "application/json";
options.body = readFileSync(env.HD_REQUEST_FILE, "utf8");
const response = await fetch(url, options);
writeFileSync(env.HD_RESPONSE_FILE, Buffer.from(await response.arrayBuffer()), {mode: 0o600});
writeFileSync(env.HD_HEADERS_FILE, JSON.stringify(Object.fromEntries(response.headers)), {mode: 0o600});
console.log(response.status);
console.log(response.headers.get("content-type") ?? "");
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hi-doctor.ai/v1/users/journal/injections/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'medication' => 'Synthetic example',
'dose' => 'TEST',
'injected_at' => '2026-10-04T12:00:00Z',
'injection_site' => 'abdomen',
'note' => 'Synthetic example'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.hi-doctor.ai/v1/users/journal/injections/"
payload := strings.NewReader("{\n \"medication\": \"Synthetic example\",\n \"dose\": \"TEST\",\n \"injected_at\": \"2026-10-04T12:00:00Z\",\n \"injection_site\": \"abdomen\",\n \"note\": \"Synthetic example\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.hi-doctor.ai/v1/users/journal/injections/")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"medication\": \"Synthetic example\",\n \"dose\": \"TEST\",\n \"injected_at\": \"2026-10-04T12:00:00Z\",\n \"injection_site\": \"abdomen\",\n \"note\": \"Synthetic example\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hi-doctor.ai/v1/users/journal/injections/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"medication\": \"Synthetic example\",\n \"dose\": \"TEST\",\n \"injected_at\": \"2026-10-04T12:00:00Z\",\n \"injection_site\": \"abdomen\",\n \"note\": \"Synthetic example\"\n}"
response = http.request(request)
puts response.read_body{
"id": "3185a308-a283-5b1f-b5fa-174a58ab8491",
"created_at": "2026-10-05T17:48:32.374222Z",
"updated_at": "2026-10-05T17:48:32.374236Z",
"medication": "Synthetic example",
"dose": "TEST",
"injected_at": "2026-10-04T12:00:00Z",
"injection_site": "abdomen",
"note": "Synthetic example"
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
Medication for this injection entry. Maximum 64 characters.
64Dose for this injection entry. Maximum 80 characters.
80Injected at timestamp in ISO 8601 format.
Injection site for this injection entry.
abdomen, thigh, upper_arm Optional note attached to the resource.
Response
Successful create an injection entry.
Unique identifier of this resource. Returned by the server; not writable.
Created at timestamp in ISO 8601 format. Returned by the server; not writable.
Updated at timestamp in ISO 8601 format. Returned by the server; not writable.
Medication for this injection entry. Maximum 64 characters.
64Dose for this injection entry. Maximum 80 characters.
80Injected at timestamp in ISO 8601 format.
Injection site for this injection entry.
abdomen, thigh, upper_arm Optional note attached to the resource.