Changelog
Notable API changes over time.
2026-10-19 — Accounting file formats (Preview)
Section titled “2026-10-19 — Accounting file formats (Preview)”New section: Accounting files. UPC Accounting, in Preview, exchanges data with other software through files only: no live bank feed, no accounting-software API sync, and no partner API for the books. The section documents the file contracts for vendors, banks and bookkeepers:
- Imports: bank statements (OFX, QFX, QBO, bank CSV and Excel, camt.052 / 053 / 054, MT940 / MT942, BAI2), open-banking JSON exports (FDX, UK Open Banking v3.1, Berlin Group NextGenPSD2, Australia CDR), and books from QuickBooks Online and Desktop, Xero, Sage, Wave, FreshBooks, Zoho Books, FEC, DATEV, SAF-T and JPK_KR. See Bank statements, Open-banking exports and Accounting software imports.
- Exports: QuickBooks Online journal CSV, IIF, Xero manual journal CSV, FEC, DATEV Buchungsstapel, SAF-T 2.00, JPK_KR, the UPC templates and a full-entity archive. See Exports and UPC templates.
- Rules: 10 MB per statement file, 25 MB per accounting-software file, XML with a DOCTYPE refused, transaction ids and entry numbers used to skip what was imported before, and a formula guard on exported text. See the overview.
- Not available: payroll register files, fixed-asset and employee templates, and some list and journal exports; each page says which.
2026-10-18 — Business resources act for the connected business
Section titled “2026-10-18 — Business resources act for the connected business”Breaking for any integration built against the earlier contract of these resources.
- A delegated token is required. Animals, invoices, breeding records, messages, content items, inventory items,
marketplace offers, sales, business profiles, and the social channel, post and engagement reads act for the business
that connected your app. They need a token from the
authorization-code grant and a business that keeps a valid
payment card on file. A client-credentials token answers
4030010010000406; no card,4030010010000407. A resource of another business answers404. A business grants their scopes on the consent page, from the ones your app declared, once United Pet Club approved a review of your app’s scopes; a self-registered app can declare only the booking scopes. See Business resources and Scopes. - Social reads are the business’s. Channels, posts and engagement are those the connected business owns, no longer those of the app’s publisher profile.
- Marketplace: new
GET /api/marketplace/v1/offersand/offers/{id};/listingsand/listings/{id}stay as aliases. The resource gainsofferCode,storefrontId,kind,catalogItemId,catalogCategoryId,pricingMode,listPriceMinorUnits,priceMinorUnits,priceStatusandupdatedAt.price(a decimal) andcategoryare gone: prices are integer minor units and may benull(seepriceStatus), and thekindfilter replacescategory(still accepted as a filter name). Drafts are listed. See Marketplace offers. - Order: new
GET /api/order/v1/salesand/sales/{id};/ordersand/orders/{id}stay as aliases. The id is the sale (the business’s part of an order), not the order. GainsorderId,orderStatus,subtotal,discount,tax,feesAndLevies,deposit,shipping;totalAmountis what the buyer pays for the sale, not the payout. See Sales. - Billing: new
GET /api/billing/v1/platform-invoices(+/{id}), what United Pet Club charged the business, withkind(PLAN/PLATFORM_FEES), minor-unit amounts, period and plan fields;/invoices(+/{id}) is now its alias. NewGET /api/billing/v1/client-invoices(+/{id}), the invoices the business issued to its clients, withisOverdue,dueAt,clientName,referenceandlines(on a get);paidAtis alwaysnullfor now. A platform-invoice page may reach 1,000 invoices deep. See Invoices. - Communication:
POST /api/communication/v1/messagestakes{ clientId, subject?, body, idempotencyKey? }and sends an in-app message to one of the business’s clients;recipientis gone andchannelaccepts onlyIN_APP. The answer gainsconversationId,clientId,postedAt(replacingqueuedAt),conversationStartedandreplayed(200on a replay,201otherwise). New refusals:409for a guest client,429past the daily caps (50 clients per business, 5 messages per client). See Messages to clients. - Animals: the list holds the animals the business owns of record; a get, update or archive also reaches one it
co-owns.
DELETEarchives the animal. Create gainsconfirmedNotDuplicate; the resource gainsupcCode,registeredName,lifeStatusandisOwnerOfRecord. See Animals. - Breeding records:
sireAnimalIdis replaced bysireAnimalIds(every sire) andservicings; gainsmatingMethod,isArtificialInsemination,matingStartedAt,matingEndedAt,expectedBirthLatestDate,createdAtandupdatedAt;matingDateanddamAnimalIdmay now benull. See Breeding records. - Business profiles: the list is the business and its brand locations. The resource gains
handle,purpose,avatarPath,relation(SELF/BRAND_LOCATION) andverifiedTier(the verified badge:NONE,PERSON,OWNERorBUSINESS). See Business profiles. - Content items:
publishedAtmay benull(never published); gainstitleLocale,createdAtandupdatedAt. See Content items. - Inventory items:
quantityOnHandis a decimal in base units (for example2.5g); gainsisActive. See Inventory items. - Errors: a business resource relays its service’s
429as well as400,403,404,409and503. See Errors.
2026-10-17 — Plan switch credit by whole months; refunds keep usage back, once per client
Section titled “2026-10-17 — Plan switch credit by whole months; refunds keep usage back, once per client”- Plan switch: an upgrade’s credit is now the whole months of the current plan after the month in progress (a
monthly plan gets none; gifts are credited too). The checkout and preview
switchobject gainsunusedMonthsandtermMonths;unusedDays/termDaysstay. - Refunds:
GET /api/sub/v1/subscriptions/{id}/refund-eligibilitygainsgrossRefundableAmountMinor,usageChargeMinorandusageLines(definitionSysName,quantity,packPriceMinor,packUnits,amountMinor): texts / WhatsApp, e-mail sends and AI credits used since the charge are kept back from the refund, sorefundableAmountMinoris net of them. New decisionUSAGE_COVERS_CHARGE.LIMIT_REACHEDnow means the client’s one self-serve refund, ever, and comes withcanRequestRefund: false. Refund rows gainusageChargeMinorandusageLines. - New:
GET /api/sub/v1/refund-policy— the signed-in caller’s refund terms (selfServeRefundAvailable,windowDays,usageChargedDefinitions), to show before a purchase.
2026-10-17 — Reference prices on booking fees
Section titled “2026-10-17 — Reference prices on booking fees”- No request or response changes. The Commission of a booking recorded below its service’s reference price is worked out on the reference price (Platform Agreement 13.5), a booking pays one Commission however it is paid, and a completed booking never settled is charged after 14 days. See Reference prices.
2026-10-15 — Promo codes on carts; seller promotions
Section titled “2026-10-15 — Promo codes on carts; seller promotions”- Promo codes:
POST /api/cart/v1/carts/{cartId}/promo-codes{ code }andDELETE /api/cart/v1/carts/{cartId}/promo-codes/{code}answer the cart plus the refused codes with areasonCode. Promo discounts in the cart detail carrycouponCodeSnapshot,cartLineId,fundedBy(SELLER/UPC) andfundedByProfileIdLogical.POST …/discountsno longer accepts a promotion or coupon from a member (403). - Seller promotions:
/api/promotion/v1/seller/…lets an approved seller or a verified organization or shelter create, publish, pause, resume and end its own promotions, add codes, and read results and the per-claim fees it was charged.GET /api/promotion/v1/me/reward-codeslists referral reward codes. - Membership dues: a seller promotion can name
listingKindCode: "MEMBERSHIP_TIER"andduesTermsCount(1–36);POST /api/membership/v1/applicationsand…/memberships/{id}/change-requeststakepromoCode, and the application / change request reads gainpromoCode,promoDiscountAmount,promoDuesTermsCount. Claims gainclaimSourceKindCodeandtermNumber. - See Promo codes and seller promotions.
2026-10-14 — A brand names the company that owns it
Section titled “2026-10-14 — A brand names the company that owns it”- The profile detail (
GET /api/profile/v1/{locale}/Profile/profiles/{profileId}and…/by-handle/{handle}) gainsbrandOwneron a brand profile (the owning company, ornull) andownedBrandson any other profile (the brands it owns; empty when none), each{ profileId, handleText, displayName }. See Brands and locations.
2026-10-12 — Pet food statistics from opted-in owners
Section titled “2026-10-12 — Pet food statistics from opted-in owners”- Two anonymous reads:
GET /api/diet/v1/public/research/foods(the foods pets of a species, size and age eat most) andGET /api/diet/v1/public/research/products/{productId}(one food’s counts, outcome mix, breakdowns and reformulation comparisons). Groups of 10 or more pets only, counts rounded to 5, anullcount is withheld. See Pet diet (public) → Food statistics.
2026-10-12 — Limits by profile, not by plan: ceiling refusals with data.ceiling
Section titled “2026-10-12 — Limits by profile, not by plan: ceiling refusals with data.ceiling”- Litter registration (
POST /api/breeding/v1/births): the fair-use rate of five litters a day (Breeding_Litter_AD_FairUse_RJ, 429) is replaced by a ceiling on litters per rolling 24 hours and on open litters, set by the owner profile’s kind, verification, profile age and trust tier. Past it: 409Breeding_Litter_AD_Ceiling_RJwithdata.ceiling={ featureCode, window, limit, used, band, resetsAtUtc, raisedBy }. - Animal listings (
/api/animallisting/v1): saved searches, showcase slots and the listing allowances are limits of the same kind, no longer plan entitlements. Past one: 409AnimalListing_AnimalListingListing_AD_Ceiling_RJwith the samedata.ceiling. - No entitlement, plan or purchase raises these limits;
raisedBylists what does (VERIFY,ACCOUNT_AGE). See Entitlements → the litter limit.
2026-10-12 — Retired plans leave the catalogue; contract packs; Audience Insights Pro
Section titled “2026-10-12 — Retired plans leave the catalogue; contract packs; Audience Insights Pro”GET /api/plan/v1/planslists only plans on sale. The Family (family-*), Breeder Pro (petpro-*) and Rescue (rescue-*) plans were retired and are no longer listed, whateverstatusyou pass. A retired plan is still readable by its code, so stored references resolve; it is never returned byrecommended-plans.- Their prices are withdrawn.
GET /api/price/v1/platform-pricesanswers theirplan:keys, andfeature:APPOINTMENT_SCHEDULING, with an emptypointsarray. - Contracts sell in three packs.
feature:CONTRACTSreturns threeUNIT_PRICEpoints,unitsPerPack10, 20 and 50 (4000, 7000 and 15000 USD minor units), each withexpiresAfterMonths24; the former pack of 10 at 3000 is gone. No plan includes contracts: everyCONTRACTSunit is bought. Choose the pack withpricePointCodeonPOST /api/sub/v1/checkout/feature-credits. - New price subject
feature:AUDIENCE_PRO(Audience Insights Pro): oneSUBSCRIPTION_RECURRINGpoint,ANNUALLY, 6000 USD minor units; no monthly point. POST /api/sub/v1/checkout/plan-refillis removed with Breeder Pro.
See Platform prices and Entitlements.
2026-10-11 — Filter a media list by several kinds or by labels
Section titled “2026-10-11 — Filter a media list by several kinds or by labels”kindonGET /api/media/v1/assets?ownerProfileId=takes a comma-separated list of asset-kind codes, for examplekind=VIDEO,EXTERNAL_VIDEO, and keeps assets of any of them. A single code works as before. Unknown codes are skipped; a list of only unknown codes returns no items.- New
labelIds: a comma-separated list of label ids keeps assets carrying any of those labels. - With either filter,
totalcounts the matching assets, so you can page withskip/take.
2026-10-11 — Change an external video’s link; covers in the media list
Section titled “2026-10-11 — Change an external video’s link; covers in the media list”- New:
PUT /api/media/v1/external-videos/{shortCode}/linkwith{ "url": "…", "fetchMetadata": true }points an external video (YouTube, Vimeo, Dailymotion, Twitch, or any web address) the member owns at a new link. The asset keeps its short code, title, caption and every place it is used. The response is the new external source (providerCode,externalId,canonicalUrl,embedUrl,thumbnailUrl, …). The same video in another URL shape changes nothing. Refusals: 400Media_Assets_VL_Request_RJ(not an http(s) URL, or not an external video), 403, 404, 409Media_Assets_AD_Duplicate_RJ(another asset already uses that video),Media_Assets_UP_State_RJ(in the trash) orMedia_Assets_UP_SharedInUse_RJ(approved for the shared library). The asset goes back to moderation. Member action only; the Partner API scopes do not cover it. GET /api/media/v1/assets?ownerProfileId=items of kindEXTERNAL_VIDEOcarry a newexternalobject:{ providerCode, url, embedUrl, thumbnailUrl }(embedUrl/thumbnailUrlabsent when unknown). Other kinds are unchanged.- YouTube and Dailymotion videos always have a
thumbnailUrlnow: when the provider’s oEmbed answers none, the provider’s standard cover address is used.
2026-10-11 — A profile’s animal list with a very large owner
Section titled “2026-10-11 — A profile’s animal list with a very large owner”GET /api/animal/v1/profiles/{owningProfileId}/animalsanswers quickly for every owner. For the platform profile, which owns the imported catalogue, the list used to fail with a 500 after about 30 seconds.- New response field
totalCapped(boolean,falseunless stated below). When a profile owns more than 10,000 live animals and more than 10,000 match the request,totalis10,000andtotalCappedistrue: show “10,000+” and page withskipuntil a page returns fewer thantakeitems. - Such a profile’s list comes in created order.
sort=createdkeeps the direction you ask for;name,species,sex,ageandcodefall back to newest-first. - Its
searchmatches the start of a call or registered name, or of the UPC code, asGET /api/animal/v1/animals/searchdoes without a breed, from 3 characters on;totalis then an estimate until a page comes back short. A shorter term is ignored, and the list comes back as if nosearchhad been sent. - Every other profile’s list is unchanged: exact
total, every sort, andsearchanywhere in the names or code.
2026-10-10 — Media search matches more fields; replace an asset’s file
Section titled “2026-10-10 — Media search matches more fields; replace an asset’s file”qonGET /api/media/v1/assets?ownerProfileId=andGET /api/media/v1/shared-media/itemssearches more. It now matches the original filename, the short code, the slug, and the title, alt text and caption of the default locale and of every translation. The query is split into words (at most 8, each up to 100 characters) and every word must appear, anywhere, case-insensitively; before, the whole string had to appear in one field. Aqthat is a media id (any GUID format) returns exactly that asset.%and_in a word act as wildcards.+inqis a space. Sendq=groomer+website(whatURLSearchParamsproduces) orq=groomer%20website; a literal plus is%2B. Until now a+was searched for literally.- New:
POST /api/media/v1/assets/{shortCode}/file?filename=&kind=replaces the file of an asset the member owns, with the raw bytes as the body and the file’sContent-Type. The asset keeps its id, short code, title, alt text, caption, folder and labels; the response is{ mediaAssetId, shortCode, slug, versionNumber, sizeBytes }. The slug changes (to{slug}-v{N}), so rebuild public file URLs from the returned slug; the old URL redirects (301) to the new one. Refusals: 400Media_Assets_VL_Request_RJ(no filename, a file of another kind, an external video), 403, 404, 409Media_Assets_UP_State_RJ(in the trash) orMedia_Assets_UP_SharedInUse_RJ(approved for the shared library), 402Media_Assets_AD_Quota_RJ(the new file does not fit the profile’s storage; nothing changed), 503Platform_Entitlement_HD_MeteringUnavailable_FL(retry). Member action only; the Partner API scopes do not cover it.
2026-10-10 — Quote sales and quote ads
Section titled “2026-10-10 — Quote sales and quote ads”- Quote ads. Marketplace offers carry a new
isQuoteAdflag. A quote ad is pricedQUOTE_REQUIREDand takes quote requests with a deposit: show Request a quote, never a price. Paused, suspended and ended ads are not returned by the public offer read. See Quote sales. - The quote flow under
/api/price/v1/quotes:requests,{id}/send,/revise,/withdraw,/accept(now requiresrevisionNumber, the revision the buyer read),/reject. Member actions only; the Partner API scopes do not cover them.GET quotes/{id}addsdepositStatus,depositRefundedMinorUnits,acceptedRevisionNumberandactivity[]. - New response codes:
Price_PriceQuote_VL_State_RJ,…_VL_Revision_RJ,…_VL_Validity_RJ,…_VL_Expired_RJ,…_VL_Deposit_RJ,…_VL_Offer_RJ,…_HD_Offer_FL,…_VL_OwnOffer_RJ,…_VL_AdInactive_RJ,…_VL_PayoutReadiness_RJ,…_HD_PayoutReadiness_FL. - Seller fees on a quote sale: Commission 1.25 % of the accepted total (from the deposit, the rest on the seller’s card), Platform Processing Fee on the deposit, Stripe Payout Fees; US$50 a month per active quote ad.
2026-10-09 — Awards are confirmed by the other side
Section titled “2026-10-09 — Awards are confirmed by the other side”- New fields on awards:
statusCodeandsourceCode, in the career portfolio’sawardsand inGET /api/profile/v1/{locale}/Profile/profiles/{profileId}/awards.sourceCodeisSELF(recorded by the profile) orISSUER(given by a business). Public reads return onlyCONFIRMED(show a “Confirmed” mark) andSELF_REPORTED(label it “Not confirmed”) awards;PENDING,DECLINEDandWITHDRAWNones are visible to the profile itself only. Existing awards readSELF/SELF_REPORTED. See Award statuses. - Awards on every profile kind. Business and place profiles can now hold awards, not only person profiles.
- Eleven new routes for confirming, accepting, declining, giving and withdrawing awards
(
…/awards/received,…/awards/{awardId}/request-confirmation | accept | decline,…/award-confirmations[…],…/given-awards[…]). They act as the profile and need permission to edit it. See Managing awards. - Changed: award writes return
{ id, statusCode }.POSTandPUT …/profiles/{profileId}/awards[/{awardId}]now answer the award’s id and its status (a linked issuer makes a new awardPENDING). A profile can hold 30 awards; declined and withdrawn ones no longer count.
2026-10-09 — Days per type of service; businesses finish their booking setup; seller fees
Section titled “2026-10-09 — Days per type of service; businesses finish their booking setup; seller fees”-
Seller fees have three names, and classes their own rates. What a provider pays is now called Commission (1.25 % on service bookings; classes 7 % in person, 17 % online; minimum 0.50; the Pro plan’s 0 % covers service bookings only, never classes), Platform Processing Fee and Stripe Payout Fees (0.25 % + 0.25 per payout, plus 2.00 in each month with a payout, at cost). Nothing changes in the booking APIs. See Fees on bookings.
-
New anonymous read:
GET /api/commission/v1/payout-fee-rates/current?country=CA, and apayoutFeesobject onGET /api/commission/v1/public/fee-sheet. See Published fee schedules. -
Slots honour a business’s days per type of service. A business can now offer a type of service only on some days and times (grooming Monday to Wednesday, training at weekends).
GET /api/scheduling/v1/services/{serviceId}/slotsreturns only starts that fit both a team member’s hours and those windows, and a booking or reschedule outside them answers409 Scheduling_SchedulingPartner_AD_Slot_RJ. Search each service separately. See Search availability. -
Grooming questions apply to grooming services only. A booking for a service the business does not class as grooming ignores the pets’ grooming answers and raises no clip or corded-coat advisory. Agreements still apply.
-
New refusal:
409 Scheduling_Provider_AD_NotReady_RJ. From a date the platform announces, a business that has not connected payouts, accepted the service fees and added a payment card cannot take new bookings.data.reasons[]lists the missing steps (PAYOUT_NOT_CONNECTED,FEE_TERMS_NOT_ACCEPTED,NO_CARD_ON_FILE). Booked appointments, slot search and reads are unaffected. A check that cannot be made answers503 Scheduling_Provider_HD_Readiness_FL(retry). See A business that is not ready for bookings.
2026-10-08 — Consent requests for several scopes
Section titled “2026-10-08 — Consent requests for several scopes”- Fixed: asking for two or more scopes on the consent page. An authorize request whose
scopelists several scopes (scope=scheduling:read appointment:write, sent as+or%20between them) showed the business This link can’t be used. The consent page now accepts both encodings. Requests with noscope(every scope your app declared) or a single scope were not affected. - Businesses can also disconnect your app from their account settings (Account → Security → Connected Apps), as well as from Dashboard → Profile → Connected Apps. The effect on your tokens and webhooks is the same; see When the business disconnects.
2026-10-08 — Career portfolios: public reads
Section titled “2026-10-08 — Career portfolios: public reads”- New: a person’s Career Portfolio.
GET /api/profile/v1/{locale}/Profile/profiles/{profileId}/career-portfolioreturns the headline, About, skills with a 1–5 comfort level, breeds, experience, education, awards and the open-to-work flag, as the caller may see them. An anonymous call receives the public view; sections it may not see come back empty and listed inlockedSections. See Career portfolios. - New: the skill catalogue and lookups.
GET …/Profile/skills/catalog(24 categories, 493 skills, localized) andGET …/Profile/career-portfolio/lookups(employment types, degree types, award kinds, work settings, job titles). - Changed:
GET …/Profile/profiles/{profileId}/portfolio-itemson a person profile now follows the person’s choice of who can see their work samples: an anonymous caller gets an empty list when they are not public. Organization profiles are unchanged.
2026-10-07 — Animal search needs a breed or a 3-character term
Section titled “2026-10-07 — Animal search needs a breed or a 3-character term”GET /api/animal/v1/animals/searchmust be narrowed. Send abreedId, or asearchterm of at least 3 characters. Any other request is refused at once withAnimal_AnimalRegistry_VL_SearchScope_RJ(400). That includes no filter at all, or onlysex,speciesId,lifeStatusorlabelIds. Before this change, such a request could run for up to a minute and then fail with a 500.- With
breedId,searchmatches anywhere in the call name, registered name or UPC code, as before.speciesIdis optional; it is taken from the breed. - Without
breedId,searchmatches the start of an animal’s call or registered name, or of its UPC code, in any letter case.maxfinds “Max” and “Maxwell’s Midnight Sun”, but not “Ch. Max of Oakridge”. - Without
breedId, results come in name order (code order for a code prefix).sortanddescendingare ignored.totalis an estimate, at most 2,000, until the last page: page withskipuntil a page returns fewer thantakeitems. That page’stotalis exact. - Response shapes, paging (
skip,takeup to 200) and the public fields returned are unchanged. To list one profile’s animals, useGET /api/animal/v1/profiles/{profileId}/animals, which needs no extra filter.
2026-09-29 — Audience upc.js version 2: referrers of in-app navigations, shorter cache for the bare URL
Section titled “2026-09-29 — Audience upc.js version 2: referrers of in-app navigations, shorter cache for the bare URL”- Referrer after a client-side navigation. On
pushState/popstatepage views,upc.jsnow sends the previous page as the referrer instead of repeatingdocument.referrer, which stays fixed at the first load. Single-page apps no longer count every in-app page as a new search, social or AI-assistant referral. Earlier data is unchanged. - Caching.
upc.{version}.js(nowupc.2.js) stays cached for a year; the bareupc.jsis now cached for one hour instead of a year. Pinupc.2.jsin your tag and change the number when a new version is announced. See The browser script. - No change to the collect endpoint, the hit fields or the responses.
2026-09-29 — Storage is metered: an upload can answer 402
Section titled “2026-09-29 — Storage is metered: an upload can answer 402”- Media uploads count against the profile’s storage. Every profile has a
STORAGE_GBallowance: 200 MB free, plus any storage add-on it holds (25 GB or 100 GB).POST /api/media/v1/upload-sessions/{id}/commitdraws the stored size of the uploaded file from the profile the upload belongs to. Thumbnails and other generated sizes draw nothing, files committed before 2026-09-29 were not counted, and deleting an asset gives its space back. - Out of storage, the commit answers
Media_Assets_AD_Quota_RJ(402) and stores nothing, withdata = { "purchase": { "featureCode": "STORAGE_ADDON_25GB", "quantity": 1 } }. Treat it like the other 402 quota refusals: tell the member they are out of storage (they can delete files to free space) and do not retry the same file until the balance has changed. A file larger than the space left is refused even when some space remains. - Only storage is metered. Litter Passes, contracts and every other entitlement are still not metered on the live platform (see the note under the next entry). No route changed, and a successful commit answers as before.
2026-09-25 — Litter records are free; the Litter Pass, contract packs and Breeder Pro
Section titled “2026-09-25 — Litter records are free; the Litter Pass, contract packs and Breeder Pro”- Registering a litter draws no entitlement on any plan.
POST /api/breeding/v1/birthsno longer answersBreeding_Litter_AD_AddonRequired_RJorBreeding_Registry_AD_PlanLimit_RJ; the only limit is a fair-use ceiling,Breeding_Litter_AD_FairUse_RJ(429), five litters per profile per 24 hours. - The Litter Pass.
POST /api/breeding/v1/births/{id}/passstamps a Litter Pass on a litter, andDELETE …/passundoes it within 24 hours (409Breeding_Litter_AD_PassLocked_RJafter). Litter reads carryhasLitterPassandlitterPass. While metering is off, the stamp draws nothing (litterPass.sourceCodeADMIN). Once it is on, the stamp draws oneLITTER_PASSESunit (sourceCodePLAN) and answers 402Breeding_Litter_AD_PassRequired_RJwithdata.purchasewhen the balance is out.GET /api/breeding/v1/me/litter-meternow namesLITTER_PASSESfor every profile, withpurchasealways present.KENNEL_LITTERSis renamedLITTER_PASSES(same definition). See Entitlements. - Waitlists need the pass. Join, offer and accept on a listing created from a litter answer
AnimalListing_Waitlist_AD_LitterPass_RJ(402) without one; a passed litter’s listing takes protected deposits on any plan. This refusal applies today, whether or not metering is on: it checks that the litter holds a pass, which its owner’s stamp gives it. See Protected deposits. - Contracts are metered once metering is on.
POST /api/contract/v1/contractsthen draws oneCONTRACTSunit and answersContract_Signing_AD_Quota_RJ(402) withdata.purchasewhen none is left; packs of 10 throughcheckout/feature-credits. Until then, a create draws nothing. - Breeder Pro. The Pet Pro plans are Breeder Pro 2 / 6 / 15 / 50 (slugs unchanged,
petpro-maxnew), yearly only:GET /api/price/v1/platform-pricesreturns oneANNUALLYpoint per plan and the newfeature:LITTER_PASSES/feature:CONTRACTSkeys.POST /api/sub/v1/checkout/plan-refillsells an active subscriber the same tier’s passes and contracts again for twelve months. See Platform prices.
2026-09-25 — The Partner API is free; apps can register themselves
Section titled “2026-09-25 — The Partner API is free; apps can register themselves”- Free, with a payment card on file. The Partner API costs nothing, for your app and for the business.
The Partner API add-on announced on 2026-09-24 was withdrawn before it was sold. Instead, a business must
keep a valid payment card on file (Dashboard → Finances → Billing) to allow an app on the consent page,
and its apps work only while it keeps one.
4030010010000407now meanspayment-card-required(title “Payment card required”); a5030010010000503withRetry-After: 5means the card could not be checked. See Booking → Partner API. - Webhooks of a business with no valid card are cancelled (the subscription stays
ACTIVE); while the card cannot be checked they wait. See Webhooks. - Self-registration.
POST https://auth.unitedpetclub.com/connect/register(RFC 7591) registers an app without signing in — for WordPress plugins, AI-built websites and AI agents. A self-registered app has no publisher, is shown to businesses as unverified, may ask only for the Partner API scopes, and must use PKCE. At most 20 registrations per address in 24 hours. See Self-registration and the new WordPress plugins and AI agents guide. - Public clients. An app registered with
token_endpoint_auth_methodnonehas no secret: it sendsclient_idwithoutclient_secretonauthorization_codeandrefresh_token, must use PKCES256(invalid_grantwithout it), cannot useclient_credentials(400 unauthorized_client), and a secret it sends is refused (401 invalid_client). See Public clients and PKCE. - Discovery.
GET https://auth.unitedpetclub.com/.well-known/oauth-authorization-server(RFC 8414) andGET https://api.unitedpetclub.com/.well-known/oauth-protected-resource(RFC 9728); a401for a missing, invalid or expired token now carriesWWW-Authenticate: Bearer resource_metadata="…". See Discovery metadata. - Fix: token responses use the RFC names.
/connect/tokenanswered camelCase JSON (accessToken,tokenType,errorDescription, …) although these pages showedaccess_token. It now answers the RFC 6749 names (access_token,token_type,expires_in,scope,refresh_token;error,error_description) withCache-Control: no-store.
2026-09-24 — Partner booking API
Section titled “2026-09-24 — Partner booking API”- Apps a business connects. A business can connect your app on the United
Pet Club consent page (
https://auth.unitedpetclub.com/connect/authorize, OAuth 2.0 authorization code with PKCE).POST /connect/tokennow also acceptsauthorization_codeandrefresh_token(refresh tokens rotate on every use and last 90 days) and HTTP Basic client authentication. See Connecting a business. /api/scheduling/v1onapi.unitedpetclub.comacts for the connected business: the business, services, open slots, booking options, estimates, appointments (book withIdempotency-Key, reschedule, cancel), clients and pets, and appointment webhooks signed with HMAC-SHA256. See the Partner API and Webhooks.- Self-service registration: register the app, its redirect URIs and scopes, and rotate its secret under Account → Developer → Applications. Businesses see and disconnect connected apps under Dashboard → Profile → Connected Apps.
- Scopes: new
scheduling:readandclient:read;appointment:read,appointment:writeandwebhook:manageare now the Partner API’s;booking:read/booking:writeare retired. The unreleased/api/appointment/v1,/api/booking/v1and/api/webhook/v1families were removed in favour of/api/scheduling/v1. - New edge codes:
0010010000400(validation),0010010000406(a client-credentials token on a route that acts for a business),0010010000407(the business has no valid payment card on file — this entry first said “lacks the Partner API add-on”; see 2026-09-25). See Errors.
2026-09-23 — A refund ends the plan
Section titled “2026-09-23 — A refund ends the plan”- Subscribers can now get refunds for plans, memberships and bought credit packs (a pack only while none of it is
used). A refund ends the subscription at once (support may choose to keep it running), so its
SUBSCRIPTIONgrants are revoked at that moment, exactly as for an immediate cancellation./checkreflects it within seconds.
2026-09-23 — Grants end when the plan ends
Section titled “2026-09-23 — Grants end when the plan ends”- Grants with source
SUBSCRIPTIONare now revoked whenever the plan behind them ends: cancelled right away, cancelled at the end of its paid period (revoked on that date), or not renewed at the end of its paid period (for example because no card is saved). Before this, a plan cancelled at the end of its period, or one that never renewed, could keep its grants. Expect a subject’s quantity to drop to zero at those moments./checkreflects it within seconds.
2026-09-21 — Offer codes
Section titled “2026-09-21 — Offer codes”- Every marketplace offer has a 10-character
offerCode(immutable, never reused), returned right afteridon the offer reads.GET /api/marketplace/v1/codes/{code}(anonymous) resolves a code — body or theUPC-OF-form, any case — to the offer, its storefront and the product’s item code;isLiveFlagisfalsefor a withdrawn offer, an unknown code is404. See Offer codes.
2026-09-20 — Booking references, preferred groom style, estimate wording
Section titled “2026-09-20 — Booking references, preferred groom style, estimate wording”POST scheduling/v1/public/bookingsacceptsreferences[](LINKurl /MEDIAmediaId, ≤ 5;MEDIAneeds a session);GET scheduling/v1/appointments/{id}returnsreferences[].PUT animal/v1/animals/{id}/coat/groom-stylesets a pet’s preferred groom style (text,referenceUrl);GET animal/v1/animals/{id}exposesgroomStylePreference*; the appointment’sanimalDetails[]carriespreferredStyleText/preferredStyleReferenceUrlas snapshotted at booking. New codeAnimal_AnimalRegistry_VL_GroomStyleUrl_RJ(400).- Grooming prices are estimates until the pet is seen — the hosted booking page now says so; partner UIs should present them the same way.
2026-09-09 — Brand profiles and locations
Section titled “2026-09-09 — Brand profiles and locations”- New anonymous Profile reads under
/profile/v1/{locale}/Profile/profiles/{profileId}:/brand(the brand a location belongs to,404when none),/locations(a brand’s locations, each with its own rating, plus a review-count-weighted roll-up),/carriers(profiles that stock or service a brand) and/carried-brands. The profile detail now embedsbrandand, for brand profiles,brandRollup. Brand profiles (purposeBRAND) are not returned by the professional directory. - Price:
GET /price/v1/pricelists/by-brand/{brandProfileId}andGET /price/v1/pricepoints/by-brand/{brandProfileId}?subjectKey=;POST /pricepoints/resolveand/previewacceptbrandProfileIdand answerresolvedFromBrandList. A location’s own price always ranks above the brand’s. See Brands and locations.
2026-09-09 — Localized forms (Form V2.0)
Section titled “2026-09-09 — Localized forms (Form V2.0)”- The form reads
GET /form/v1/public/deployments/{id}/render,/form/v1/deployments/{id}/render,/form/v1/templates/{id}/preview,/form/v1/templatesand/form/v1/definitions/{id}accept?locale=. With it, everysysName/sysTitle/sysPrompt/sysHelp/sysLabelin the payload is resolved for that locale (requested → language default → en-US → authored text, per row);displayLocaleCodeandavailableLocalesare new on the render payload. Without it the payload is unchanged. - New owner routes to translate a version:
GET /form/v1/versions/{id}/locales,GET|PUT|DELETE /form/v1/versions/{id}/locales/{locale}. Allowed on published versions. - The 15 platform templates are available in all 72 platform locales.
2026-09-08 — Corded coats + localized booking questions (Scheduling)
Section titled “2026-09-08 — Corded coats + localized booking questions (Scheduling)”coatConditionCode(estimate, bookinganimals[], visit assessment) acceptsCORDED— the coat is kept in cords. Not matting; hours of drying. Raises the newCORDED_COATadvisory (regionCode: null) under the provider’sCORDED_COAT_MODE; two new booking rejections:409 Scheduling_Booking_VL_CordedCoat_RJ(acknowledgement required) and409 Scheduling_Booking_VL_CordedRefused_RJ.advisories[].regionCodeis now nullable (null = the whole coat).- New lookups:
GET /scheduling/v1/lookups/intake-questions?locale=&audience=(every booking / visit question with localized prompt, help and fixed answers) andGET /scheduling/v1/lookups/coat-advisories?locale=(advisory texts +textHash).GET /providers/{id}/grooming-optionsgainedintakeQuestions[](the same rows, filtered to what the provider asks).bookingQuestionsgainedcordedCoatMode/cordedCoatText. - Price
COAT_CONDITIONvocabulary gainedCORDED; the estimate also addsCORDEDto the pet’sCOAT_TEXTUREwhen the coat is corded. - The intake-question and coat-advisory lookups answer in all 72 platform locales (
?locale=), with the usual fallback to the language default and en-US.
2026-09-07 — Double-coat declaration on mixed-breed dogs
Section titled “2026-09-07 — Double-coat declaration on mixed-breed dogs”The animal read (GET /animal/v1/animals/{id}) gained three optional fields:
hasDoubleCoat—true/false, ornullwhen nobody has declared it. Only ever set on mixed-breed dogs; purebreds and other species always readnull, because their coat is a breed fact served by the breed guide instead.doubleCoatDeclaredByRole—OWNERorCARE_CIRCLE(a groomer, vet or trainer holding an access grant on the animal);nullwhile undeclared.doubleCoatDeclaredAtUtc.
Two new authenticated routes:
PUT /animal/v1/animals/{id}/coat/double-coatwith{ "doubleCoat": "UNKNOWN" | "YES" | "NO" }— accepted from the owner or any active care-circle grantee;UNKNOWNclears the declaration. Rejected withAnimal_AnimalRegistry_VL_DoubleCoat_RJ(400) when the animal is not a mixed-breed dog. Outsiders receive the same not found answer as for any other animal they cannot see.GET /animal/v1/animals/{id}/access/me— the calling profile’s own standing on the animal (isOwner,grantScope,inCareCircle). Reveals nothing about other profiles.
Treat an absent field as unknown: older responses do not carry it.
2026-08-11 — Self-serve plan & credit purchases
Section titled “2026-08-11 — Self-serve plan & credit purchases”Customers can now buy platform plans and one-time feature-credit packs directly in the United Pet Club apps. No partner API surface changed, but integrations reading entitlements will observe the effects:
- New grants with source
SUBSCRIPTIONappear in subject grant ledgers within seconds of a purchase, and/checkavailability can increase between calls. - A plan upgrade supersedes the previous plan’s grants (they are revoked, not stacked) — treat stored grant ids as ephemeral and re-read rather than assuming an old grant is still active.
See the Entitlements guide for the recommended check/consume pattern.