PracticePacketV1
Practice packet format v1 (#1805). Aggregates only: money is integer cents in `currency`, counts are nonnegative integers, dates are YYYY-MM-DD and months YYYY-MM. Labels are reviewed display labels and carry the email and phone tripwires; no other free text is accepted. Every month has its practice totals, every channel its spend row and every therapist its service and retention rows; acquisition rows may be sparse (an absent therapist and channel pair is zero) because each month's rows must add up to the month's practice new clients.
Properties
| Name | Type | Description |
|---|---|---|
| formatVersion | string | |
| companyId | string | |
| currency | string | A supported two-decimal ISO 4217 code |
| timezone | string | An IANA Area/Location time zone |
| reportWindow | object | Inclusive whole months; `end` is the cutoff. |
| history | object | The service-value window runs from `start` to the cutoff and must not start after the report window; `complete` claims full practice history, so no client may be active at an opening snapshot before ` |
| definitions | object | |
| sources | array | |
| approval | object | |
| reconciliation | object | |
| therapists | array | |
| channels | array | At least one channel; a channel with no spend still sends its explicit zero spend row. |
| acquisition | array | Actual new clients by month, first therapist and channel (`unattributed` when no channel is documented). |
| practiceAcquisition | array | |
| spend | array | Approved channel spend per month (explicit 0 for none); `direct` is therapist-specific spend. The rest is split by acquired-client share. |
| serviceValue | array | |
| practiceServiceValue | object | |
| acquiredCohorts | array | |
| retention | array | |
| practiceRetention | array |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://artifacts.apis.io/medianfi-com/json-schema/medianfi-com-practice-packet-v1-schema.json",
"title": "PracticePacketV1",
"description": "Practice packet format v1 (#1805). Aggregates only: money is integer cents in `currency`, counts are nonnegative integers, dates are YYYY-MM-DD and months YYYY-MM. Labels are reviewed display labels and carry the email and phone tripwires; no other free text is accepted. Every month has its practice totals, every channel its spend row and every therapist its service and retention rows; acquisition rows may be sparse (an absent therapist and channel pair is zero) because each month's rows must add up to the month's practice new clients.\n",
"x-generated": "2026-10-30",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/medianfi-com-openapi.json#/components/schemas/PracticePacketV1",
"type": "object",
"additionalProperties": false,
"required": [
"formatVersion",
"companyId",
"currency",
"timezone",
"reportWindow",
"history",
"definitions",
"sources",
"approval",
"reconciliation",
"therapists",
"channels",
"acquisition",
"practiceAcquisition",
"spend",
"serviceValue",
"practiceServiceValue",
"acquiredCohorts",
"retention",
"practiceRetention"
],
"properties": {
"formatVersion": {
"type": "string",
"enum": [
"practice-packet/v1"
]
},
"companyId": {
"type": "string",
"format": "uuid"
},
"currency": {
"type": "string",
"pattern": "^[A-Z]{3}$",
"description": "A supported two-decimal ISO 4217 code"
},
"timezone": {
"type": "string",
"description": "An IANA Area/Location time zone"
},
"reportWindow": {
"type": "object",
"additionalProperties": false,
"required": [
"start",
"end"
],
"description": "Inclusive whole months; `end` is the cutoff.",
"properties": {
"start": {
"type": "string",
"format": "date"
},
"end": {
"type": "string",
"format": "date"
}
}
},
"history": {
"type": "object",
"additionalProperties": false,
"required": [
"start",
"complete"
],
"description": "The service-value window runs from `start` to the cutoff and must not start after the report window; `complete` claims full practice history, so no client may be active at an opening snapshot before `start`.",
"properties": {
"start": {
"type": "string",
"format": "date"
},
"complete": {
"type": "boolean"
}
}
},
"definitions": {
"type": "object",
"additionalProperties": false,
"required": [
"definitionVersion",
"attributionPolicyVersion",
"costPolicyVersion",
"channelMappingVersion",
"spendAllocationRule",
"retentionWindowDays"
],
"properties": {
"definitionVersion": {
"type": "string"
},
"attributionPolicyVersion": {
"type": "string"
},
"costPolicyVersion": {
"type": "string"
},
"channelMappingVersion": {
"type": "string"
},
"spendAllocationRule": {
"type": "string",
"enum": [
"acquired_client_share_v1"
],
"description": "The allocation the API applies. Therapist-specific spend first; each channel-month's remaining spend is split by that channel's new clients per therapist, floors first, the leftover cents to the largest remainders, ties by therapist key."
},
"retentionWindowDays": {
"type": "integer",
"enum": [
90
]
}
}
},
"sources": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"key",
"label",
"feeds",
"dateBasis",
"coverageStart",
"coverageEnd",
"extractedAt"
],
"properties": {
"key": {
"type": "string"
},
"label": {
"type": "string"
},
"feeds": {
"type": "array",
"items": {
"type": "string",
"enum": [
"acquisition",
"attribution",
"spend",
"serviceValue",
"retention"
]
},
"description": "acquisition decides first-ever clients (visits) and serviceValue collections and costs, both from history.start; attribution (channels), spend and retention from the report window start"
},
"dateBasis": {
"type": "string",
"enum": [
"appointment_date",
"service_date",
"payment_date",
"pay_date",
"posting_date"
],
"description": "The date that assigns this source's rows to a month"
},
"coverageStart": {
"type": "string",
"format": "date"
},
"coverageEnd": {
"type": "string",
"format": "date"
},
"extractedAt": {
"type": "string",
"format": "date-time",
"description": "When the export was pulled. It must fall after coverageEnd has ended in the packet's timezone, because an export pulled on that day misses the rest of it."
}
}
}
},
"approval": {
"type": "object",
"additionalProperties": false,
"required": [
"approvedBy",
"approvedAt",
"privacyReviewed"
],
"properties": {
"approvedBy": {
"type": "string"
},
"approvedAt": {
"type": "string",
"format": "date-time"
},
"privacyReviewed": {
"type": "boolean",
"enum": [
true
]
}
}
},
"reconciliation": {
"type": "object",
"additionalProperties": false,
"required": [
"status",
"railOverlapRemovedCents",
"pendingExcludedCount",
"failedExcludedCount"
],
"properties": {
"status": {
"type": "string",
"enum": [
"reconciled"
],
"description": "The approver's attestation that the sources reconcile"
},
"railOverlapRemovedCents": {
"type": "integer",
"minimum": 0
},
"pendingExcludedCount": {
"type": "integer",
"minimum": 0
},
"failedExcludedCount": {
"type": "integer",
"minimum": 0
}
}
},
"therapists": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"key",
"label",
"role"
],
"properties": {
"key": {
"type": "string"
},
"label": {
"type": "string"
},
"role": {
"type": "string",
"enum": [
"clinician",
"owner",
"unassigned"
]
}
}
}
},
"channels": {
"type": "array",
"minItems": 1,
"description": "At least one channel; a channel with no spend still sends its explicit zero spend row.",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"key",
"label"
],
"properties": {
"key": {
"type": "string",
"description": "snake_case; `unattributed` is reserved"
},
"label": {
"type": "string"
}
}
}
},
"acquisition": {
"type": "array",
"description": "Actual new clients by month, first therapist and channel (`unattributed` when no channel is documented).",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"month",
"therapist",
"channel",
"newClients"
],
"properties": {
"month": {
"type": "string"
},
"therapist": {
"type": "string"
},
"channel": {
"type": "string"
},
"newClients": {
"type": "integer",
"minimum": 0
}
}
}
},
"practiceAcquisition": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"month",
"newClients"
],
"properties": {
"month": {
"type": "string"
},
"newClients": {
"type": "integer",
"minimum": 0
}
}
}
},
"spend": {
"type": "array",
"description": "Approved channel spend per month (explicit 0 for none); `direct` is therapist-specific spend. The rest is split by acquired-client share.",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"month",
"channel",
"sourceSpendCents",
"direct"
],
"properties": {
"month": {
"type": "string"
},
"channel": {
"type": "string"
},
"sourceSpendCents": {
"type": "integer",
"minimum": 0
},
"direct": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"therapist",
"cents"
],
"properties": {
"therapist": {
"type": "string"
},
"cents": {
"type": "integer",
"minimum": 0
}
}
}
}
}
}
},
"serviceValue": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"therapist",
"grossCollectionsCents",
"refundsCents",
"directCostCents",
"directCostUnknownReason",
"uniqueClientsServed"
],
"properties": {
"therapist": {
"type": "string"
},
"grossCollectionsCents": {
"type": "integer",
"minimum": 0
},
"refundsCents": {
"type": "integer",
"minimum": 0
},
"directCostCents": {
"type": [
"integer",
"null"
],
"minimum": 0
},
"directCostUnknownReason": {
"type": [
"string",
"null"
],
"enum": [
"owner_policy_pending",
"not_supplied",
null
]
},
"uniqueClientsServed": {
"type": "integer",
"minimum": 0,
"description": "Distinct clients served, including those with zero collections"
}
}
}
},
"practiceServiceValue": {
"type": "object",
"additionalProperties": false,
"required": [
"grossCollectionsCents",
"refundsCents",
"uniqueClientsServed"
],
"properties": {
"grossCollectionsCents": {
"type": "integer",
"minimum": 0
},
"refundsCents": {
"type": "integer",
"minimum": 0
},
"uniqueClientsServed": {
"type": "integer",
"minimum": 0,
"description": "Deduplicated across therapists independently"
}
}
},
"acquiredCohorts": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"month",
"therapist",
"channel",
"newClients",
"netCollectionsCents"
],
"properties": {
"month": {
"type": "string"
},
"therapist": {
"type": "string"
},
"channel": {
"type": "string"
},
"newClients": {
"type": "integer",
"minimum": 0
},
"netCollectionsCents": {
"type": "integer"
}
}
}
},
"retention": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"month",
"therapist",
"openingActive",
"retainedOpening",
"closingActive",
"newClients",
"reactivated",
"transfersIn",
"transfersOut"
],
"properties": {
"month": {
"type": "string"
},
"therapist": {
"type": "string"
},
"openingActive": {
"type": "integer",
"minimum": 0
},
"retainedOpening": {
"type": "integer",
"minimum": 0
},
"closingActive": {
"type": "integer",
"minimum": 0
},
"newClients": {
"type": "integer",
"minimum": 0
},
"reactivated": {
"type": "integer",
"minimum": 0
},
"transfersIn": {
"type": "integer",
"minimum": 0
},
"transfersOut": {
"type": "integer",
"minimum": 0
}
}
}
},
"practiceRetention": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"month",
"lookbackComplete",
"openingActive",
"retainedOpening",
"closingActive",
"newClients",
"reactivated"
],
"properties": {
"month": {
"type": "string"
},
"lookbackComplete": {
"type": "boolean"
},
"openingActive": {
"type": "integer",
"minimum": 0
},
"retainedOpening": {
"type": "integer",
"minimum": 0
},
"closingActive": {
"type": "integer",
"minimum": 0
},
"newClients": {
"type": "integer",
"minimum": 0
},
"reactivated": {
"type": "integer",
"minimum": 0
}
}
}
}
}
}
Work with this as data
Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
curl "https://apis.io/api/v1/json-schemas/medianfi-com-practice-packet-v1"
curl "https://apis.io/api/v1/json-schemas?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.