> For the complete documentation index, see [llms.txt](https://docs.stellic.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.stellic.com/stellic-partner-api/hold/update-a-student-hold.md).

# Update a student hold

Use this endpoint to change a hold's type, move it to another student, or update the note and link the student sees. Every call needs `student_id` (the student's SIS ID; usernames aren't accepted here) and `hold_code`, even if they don't change. The hold's term and its campus and level limits can't be changed; to change them, remove the hold and place a new one.

## PUT /holds/student\_holds/{sis\_id}

>

```json
{"openapi":"3.0.0","info":{"title":"Stellic for Developers","version":"1.0"},"tags":[{"name":"Hold"}],"servers":[{"url":"https://{institution}.stellic.com/partnerapi/v1","variables":{"institution":{"default":"{institution}","description":"Your institution's Stellic subdomain: the part before `.stellic.com` in the URL you use to sign in. It becomes the host in every request, as in `https://{institution}.stellic.com/partnerapi/v1/...`. Replace the `{institution}` placeholder with your subdomain before sending."}}}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Personal Access Token issued by your Stellic integration partner. Send it as `Authorization: Bearer <token>` on every request. One token per institution; do not share across environments."}},"schemas":{"StudentHoldRequest":{"type":"object","properties":{"student_id":{"type":"string","description":"The student's SIS ID. `POST` also accepts the student's username; `PUT` accepts only the SIS ID and reports a username under `failed`."},"hold_code":{"type":"string","description":"The code of one of your institution's hold types. It sets the hold's title, description, and blocked activities."},"note":{"type":"string","description":"Text for this student, shown with the hold type's description. Up to 300 characters. On `PUT`, an empty value leaves the current note in place."},"url_text":{"type":"string","description":"Text shown for the link. Up to 200 characters. On `PUT`, an empty value leaves the current text in place."},"url_link":{"type":"string","description":"The link shown to the student. Up to 200 characters. On `PUT`, an empty value leaves the current link in place."},"term_code":{"type":"string","description":"`POST` only (`PUT` ignores it). The SIS term code of the one term the hold applies to. When it's omitted or doesn't match a term, the hold applies to every term, with no error."}}},"StudentHoldResponse":{"type":"object","description":"A serialized hold record, returned under the `hold` key.","properties":{"activities":{"type":"array","description":"Activity names this hold blocks, as plain strings (not objects). Empty when the hold type is inactive or has no enforced activity. Possible values are `disallow_register_activity`, `disallow_drop_activity`, and `hide_grade_activity`.","items":{"type":"string"}},"campuses":{"type":"array","description":"Campuses the hold is limited to. Empty means every campus. Holds placed through the API never set this; holds loaded by your data sync can.","items":{"type":"object","properties":{"name":{"type":"string"},"screen_name":{"type":"string"}}}},"code":{"type":"string","description":"The hold type's code (the `hold_code` you sent)."},"description":{"type":"string","description":"The hold type's description. Displayed along with the title."},"enrollment_levels":{"type":"array","description":"Enrollment levels the hold is limited to. Empty means every level. Holds placed through the API never set this; holds loaded by your data sync can.","items":{"type":"object","properties":{"display_name":{"type":"string"},"name":{"type":"string"}}}},"note":{"type":"string","description":"The per-student note you sent, or an empty string."},"semester":{"type":"string","nullable":true,"description":"Term name when the hold is term-scoped (a matching `term_code` was sent), otherwise `null`."},"sis_id":{"type":"string","description":"The hold's `sis_id`."},"title":{"type":"string","description":"The hold type's title. Displayed to the student."},"url_link":{"type":"string","description":"The link you sent, or an empty string."},"url_text":{"type":"string","description":"The link placeholder text you sent, or an empty string."},"year":{"type":"integer","nullable":true,"description":"Term year when the hold is term-scoped, otherwise `null`."}}}}},"paths":{"/holds/student_holds/{sis_id}":{"put":{"tags":["Hold"],"parameters":[{"name":"sis_id","in":"path","required":true,"description":"Hold's `sis_id` (the partner-chosen identifier from POST).","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","allOf":[{"$ref":"#/components/schemas/StudentHoldRequest"},{"type":"object","properties":{"note":{"type":"string"}}}],"required":["student_id","hold_code"]}}}},"responses":{"200":{"description":"Returned for both success and for validation or domain errors. Branch\non the `success` field in the body, not the HTTP status.\n\nOn success, `success` is `true`. `fields_updated` lists the fields that\nchanged and `failed` lists the fields that could not be applied, each\nwith a per-field message. A `200` does not mean every field applied;\nread both. The full hold is under `hold`. An unknown `hold_code` or an\nunknown `student_id` lands in `failed` while the other valid fields\nstill save, so partial success is normal.\n\nOn error, `success` is `false` and the body is\n`{\"success\": false, \"message\": {\"code\": ..., \"text\": ...}}`.\n`message.code` is `404` when no hold matches `sis_id`. It is `400` for a\nmissing `student_id` or `hold_code`, for any change to a hold whose\nstudent is archived (including moving it to an archived student),\nor for any other unexpected failure; the text is the generic\n`We are unable to process your request at the moment. Please try again\nlater.` The HTTP status is still `200` in every one of these cases.","content":{"application/json":{"schema":{"type":"object","allOf":[{"type":"object","properties":{"success":{"type":"boolean"}}},{"type":"object","properties":{"fields_updated":{"type":"object","properties":{"hold_type":{"type":"string"},"student":{"type":"string"},"note":{"type":"string"},"url_text":{"type":"string"},"url_link":{"type":"string"}}}}},{"type":"object","properties":{"failed":{"type":"object"}}},{"type":"object","properties":{"hold":{"$ref":"#/components/schemas/StudentHoldResponse"}}}]}}}},"401":{"description":"Missing or invalid Bearer token. This is the only genuine error HTTP\nstatus; auth is checked before the view runs."},"403":{"description":"Your IP address isn't on the allowlist for this endpoint. Contact Stellic to add it; the response includes the `client_ip` Stellic saw.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"client_ip":{"type":"string"}}}}}}}}}}}
```

#### What happens after the call

* The fields that could be applied are saved right away and take effect on the student's next blocked activity. `fields_updated` lists them, and `failed` lists any that couldn't be applied.

#### Notes

{% hint style="warning" %}
**Errors come back with HTTP 200, and a successful call can still skip fields.** Check `success`, then `failed`. An unknown `hold_code` or `student_id` is reported in `failed` with `success: true`, and the other fields are still saved.
{% endhint %}

* **A username in `student_id` fails every time.** It's reported in `failed`, even when you aren't moving the hold.
* **`note`, `url_text`, and `url_link` can't be cleared.** An empty or `null` value leaves the current one in place.
* **Holds on archived students can't be changed.** The call returns `message.code` 400 with the generic message, and so does moving a hold to an archived student.

#### Related APIs

* [`GET /holds/student_holds/{sis_id}`](/stellic-partner-api/hold/read-a-student-hold.md) to read the hold.
* [`DELETE /holds/student_holds/{sis_id}`](/stellic-partner-api/hold/remove-a-student-hold.md) to remove it.
* [`POST /holds/student_holds`](/stellic-partner-api/hold/place-a-hold-on-a-student.md) to place a new hold.
