Azalea Pets keeps a living record of a pet: profile, timeline, weigh-ins, vet visits, and a care schedule of medications, vaccines and appointments. This API lets an assistant the owner has connected read that record and add to it. It is add-only: there is no edit, delete, chat, photo upload or email. Only pets the owner owns are visible; everything else answers 404.
Rules for assistants. These apply to every integration and are part of the Terms.
Send Authorization: Bearer <token> on every /v1 request. Two kinds of token work.
Authorization-code flow, public clients, S256 only, exact-match redirect URIs. Metadata is at /.well-known/oauth-authorization-server. To register a client and redirect URI, email hello@azaleapets.com.
| Step | Where | Notes |
|---|---|---|
| 1. Authorize | GET https://azaleapets.com/authorize.html | response_type=code, client_id, redirect_uri, code_challenge, code_challenge_method=S256, optional state and scope. The owner signs in (or creates a free account, 13+) and approves. We redirect back with code, state and iss, or error=access_denied. |
| 2. Token | POST /oauth/token | Form-encoded or JSON: grant_type=authorization_code, client_id, code, code_verifier, redirect_uri. Codes last 5 minutes and work once. |
| 3. Refresh | POST /oauth/token | grant_type=refresh_token, client_id, refresh_token. Access tokens last 1 hour. Refresh tokens last 60 days and rotate on every use: store the new one. Reusing an old refresh token revokes the whole connection. |
| 4. Revoke | POST /oauth/revoke | token. Always answers 200. Owners can also disconnect in the app under Settings → Connected assistants. |
Scopes: pets:read and pets:write. Both are granted if scope is omitted.
In the Azalea Pets app, open Settings → Connected assistants → Create key. The key (azp_key_…) is shown once, carries both scopes, and can be removed at any time. Up to 5 keys per account. Treat it like a password.
curl https://api.azaleapets.com/v1/pets \
-H "Authorization: Bearer azp_key_..."
Full request and response schemas are in openapi.json. Bodies are JSON, 64 KB at most. Dates are YYYY-MM-DD. Pass the owner's IANA time zone as tz so "today" is their today.
| Operation | Request | What it does |
|---|---|---|
get_account | GET /v1/me | Plan, limits, today's usage, number of pets. |
list_pets | GET /v1/pets | The owner's pets. Start here to get ids. |
add_pet | POST /v1/pets | name, species, optional breed, sex, birthday, birthday_is_approximate. Conditions and medications can't be set here. Same name = duplicate. |
get_pet | GET /v1/pets/{pet_id} | Profile, owner-entered conditions, medications and vet, latest weight, and Azalea's cached description of the pet. An approximate birthday comes back as an age, never a date. |
get_timeline | GET /v1/pets/{pet_id}/timeline | Notes, weigh-ins, vet visits, milestones, photo captions. kind, since, limit (default 50, max 200). |
get_care_schedule | GET /v1/pets/{pet_id}/care | Medications, vaccines, appointments with a status: overdue, past_unconfirmed, due_soon, upcoming, unscheduled, done. |
get_vet_summary | GET /v1/pets/{pet_id}/vet-summary | A summary the owner can hand to their vet. Can take up to a minute. 5 per day. Show it as written. |
log_weight | POST /v1/pets/{pet_id}/weights | value and unit (lb or kg, required; ask, never assume), optional date, note. |
add_note | POST /v1/pets/{pet_id}/notes | text (up to 1000 characters), optional date. |
log_vet_visit | POST /v1/pets/{pet_id}/vet-visits | A visit that already happened: optional reason, notes, date. For a future visit use add_care_item. |
add_care_item | POST /v1/pets/{pet_id}/care | kind (appointment, medication, vaccine), name, optional dose, next_due, due_time, notes. |
complete_care_item | POST /v1/pets/{pet_id}/care/{item_id}/complete | Marks an item done. Optional date. |
curl -X POST https://api.azaleapets.com/v1/pets/PET_ID/weights \
-H "Authorization: Bearer azp_key_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 7f3c1e52-weigh-in" \
-d '{"value": 11.2, "unit": "lb", "tz": "America/New_York"}'
201 Created
{"entry": {"id": 4821, "kind": "weight", "date": "2026-09-22", "title": "Weigh-in",
"text": "[via assistant]", "weight": {"lbs": 11.2, "kg": 5.08}}}
200 with "duplicate": true means the same record was already there and nothing was added. Tell the owner that; don't try again.Idempotency-Key header (1–120 characters of A-Z a-z 0-9 _ - : .) per intended write and reuse it on retries. Keys are honoured for 24 hours. A replay returns the original response with Idempotent-Replay: true and costs no budget.422 implausible_weight with the plausible range. Read the number and unit back to the owner. Don't change it and retry. If it really is right, the owner logs it in the app.[via Muse] or [via assistant] prefix so the owner can see where they came from.| Plan | Pets | Reads / day | Writes / day | Requests / minute | Vet summaries / day |
|---|---|---|---|---|---|
| Free | 2 | 300 | 30 | 60 | 5 |
| Premium, Founder | Unlimited | 2,000 | 200 | 120 | 5 |
Days are UTC. The API never bypasses a limit that exists in the app and never puts anything health-related behind a paywall. Over a limit you get 429 with Retry-After; a third pet on the free plan answers 402 plan_limit. Upgrades happen in the Azalea Pets app.
Every error is JSON: {"error": "code", "message": "plain language"}. The message is safe to relay to the owner.
| Status | Codes | What to do |
|---|---|---|
| 400 | invalid_request | Fix the field named in the message. |
| 401 | invalid_token | Refresh the token, or ask the owner to reconnect. |
| 402 | plan_limit | Explain the plan limit. Don't retry. |
| 403 | insufficient_scope, account_disabled, connector_not_available | Don't retry. |
| 404 | not_found | No such pet or record for this owner. |
| 409 | request_in_progress | Wait and retry with the same Idempotency-Key. |
| 413 | payload_too_large | Bodies are limited to 64 KB. |
| 422 | implausible_weight, idempotency_key_reused | Confirm with the owner, or use a new key for a new request. |
| 429 | rate_limited, daily_budget | Wait for Retry-After seconds. |
| 502 | summary_failed | Try the vet summary again in a minute. |
| 503 | connector_disabled, temporarily_unavailable | Try again later. |
Owners choose what to connect and can disconnect at any time. What is shared, and what never is, is set out in the Privacy Policy; API acceptable use is in the Terms. Azalea Pets is for people 13 and older and is currently US-English. Questions, client registration, or a security report: hello@azaleapets.com.