Upload Provider Photo
Uploads a provider's profile picture and returns the updated provider.
Endpoint
POST /v2/providers/{provider_id}/photo
Path Parameters
| Parameter |
Type |
Required |
Description |
provider_id |
string |
Yes |
The treating provider. |
Request Body
| Part |
Type |
Required |
Description |
file |
file |
Yes |
JPEG or PNG, max 2 MB. |
Request
curl --location '{base_url}/v2/providers/2094/photo' \
--header 'Authorization: Bearer JWT_TOKEN' \
--form 'file=@provider-photo.jpg'
Response
Success Response
Code: 200 OK
{
"id": "2094",
"onboarding_provider_id": "d27a6b10-9f34-4e82-b5c1-7a03e8946fd2",
"user_id": "2094",
"first_name": "Morgan",
"middle_name": null,
"last_name": "Delgado",
"email": "m.delgado@example.com",
"mobile": "+1-555-0155",
"npi": "1740398215",
"license": "PT-30914",
"speciality": "PHYSICAL_THERAPY",
"sub_specialities": [],
"qualifications": [
"DPT"
],
"external_reference_id": "provider-4471",
"patient_scoped": false,
"photo_url": "https://assets.example.com/providers/2094-photo.jpg",
"signature_url": null,
"status": "ACTIVE",
"online_booking_enabled": true,
"clinics": [
{
"clinic_id": "5831",
"onboarding_clinic_id": "b41f7c92-5e08-4a13-8d6f-2c9147ab3e5d",
"status": "ACTIVE",
"online_booking_enabled": true,
"hours": [
{
"days_of_week": [
"MONDAY",
"TUESDAY"
],
"start_time": "08:00",
"end_time": "17:00"
}
]
}
],
"home_health": null,
"created_at": "2026-08-27T14:30:00Z",
"updated_at": "2026-08-27T14:30:00Z"
}
Response Fields
| Field |
Type |
Description |
id |
string or null |
The provider id. null while status is ONBOARDING.. |
onboarding_provider_id |
string or null |
The provider's onboarding-record UUID. |
user_id |
string or null |
The provider's user id. Same value as the provider id; both are returned rather than leaving that implicit. |
first_name |
string or null |
|
middle_name |
string or null |
|
last_name |
string or null |
|
email |
string or null |
|
mobile |
string or null |
|
npi |
string or null |
|
license |
string or null |
|
speciality |
string or null |
The record's primary speciality. |
sub_specialities |
array of string |
|
qualifications |
array of string |
|
external_reference_id |
string or null |
Your own identifier for this provider. Stored only — it has no effect on Spry behaviour. |
patient_scoped |
boolean |
When true, restricts the provider to only their own assigned patients (HIPAA minimum-necessary). When false (default), the provider can access all patients in the organisation. |
photo_url |
string or null |
A fetchable URL. It may be a time-limited signed URL, so fetch it rather than storing it. |
signature_url |
string or null |
A fetchable URL. Treat it as time-limited and fetch it rather than storing it. In environments where signing is unavailable the raw stored value is returned, which isn't fetchable. |
status |
string or null |
ONBOARDING until the record is published, then ACTIVE; INACTIVE once deleted. |
online_booking_enabled |
boolean or null |
Whether this record is bookable through online booking. |
clinics |
array of object |
See Clinics. |
home_health |
object or null |
Home-visit settings for this provider. null when the provider has no home-visit configuration. See Home Health. |
created_at |
string (date-time) or null |
|
updated_at |
string (date-time) or null |
|
Clinics
| Field |
Type |
Description |
clinic_id |
string or null |
The clinic this record belongs to. |
onboarding_clinic_id |
string or null |
The clinic's onboarding-record UUID. Always present for clinics created through onboarding, and the only way to address one before it's published. |
status |
string or null |
ONBOARDING until the record is published, then ACTIVE; INACTIVE once deleted. |
online_booking_enabled |
boolean or null |
Whether this record is bookable through online booking. |
hours |
array of object |
Working hours, as one entry per distinct daily pattern. See Hours. |
Error Response
Code: 400 Bad Request
{
"code": "bad_request",
"message": "Validation failed",
"errors": [
{
"field": "file",
"message": "must be a JPEG or PNG no larger than 2 MB"
}
]
}
Every error has the same shape — a machine-readable code, a message, and an errors[] array that's empty when there's nothing field-specific to report. The HTTP status is authoritative.
| Status |
code |
Meaning |
400 Bad Request |
bad_request |
The request body or parameters failed validation. errors[] names the offending fields. |
401 Unauthorized |
unauthorized |
The access token is missing, malformed or expired. |
403 Forbidden |
forbidden |
The request references a resource outside the token's organisation or clinic scope. |
404 Not Found |
not_found |
No such resource, or it's outside your scope. |
429 Too Many Requests |
rate_limited |
Rate limit exceeded. Back off and retry. |
500 Internal Server Error |
internal_error |
Unexpected server error. |
502 Bad Gateway |
upstream_error |
Upstream service failed or timed out. |
Notes
photo_url is read-only on Create Provider and Update Provider — this is the only way to set it.
- A file that isn't JPEG or PNG, or exceeds 2 MB, is rejected with
400 bad_request.
- Replaces any photo already set for the provider.