> 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/catalog-sections/add-a-restriction-to-a-section.md).

# Add a restriction to a section

Use this endpoint to control who can see, register for, or drop a section, or to hold reserved seats for a group of students, for example limiting a section to honors students. A restriction targets one section (`section` in the body), applies an `action` to a set of students chosen by `type`, and uses `operator` to say whether it applies to students in the set (`eq`) or outside it (`neq`). Restrictions take effect only at institutions with section restrictions turned on.

## POST /catalog/section/restriction/{id}

>

```json
{"openapi":"3.0.0","info":{"title":"Stellic for Developers","version":"1.0"},"tags":[{"name":"Catalog Sections"}],"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":{"SectionRestrictionRequest":{"type":"object","properties":{"section":{"description":"Catalog ID of the section to restrict (the section ID your data sync carries), for example `156798` or `Fall2020-16759`.","type":"string"},"type":{"description":"Restriction type. One of `campus`, `concentration`, `department`, `enrollment_level`, `program`, `raw`, `raw_pre_req`, `school`, `student_level`, `tags`, `all_students`. A section can have only one restriction of each type. Name the students in `student_sets` with the key for the type: `student_level` uses `level`, `tags` uses `tags`, `all_students` uses `has_all_students: true`, and `campus`, `concentration`, `department`, `enrollment_level`, `program`, and `school` use the type name. `raw` and `raw_pre_req` have no key and take no rule text.","type":"string"},"operator":{"enum":["eq","neq","info"],"type":"string","description":"Use `eq` to apply the action to students who match the set. Use `neq` to apply the action to students who do not match the set. `info` shows the restriction as an informational note without filtering. Defaults to `info` when omitted. Any other value is stored as `info` without an error."},"student_sets":{"description":"Student sets the restriction targets. Each entry names one set with the key that matches `type` (see `type`). The platform reads every key in an entry whatever the `type`, so don't mix keys. For `type: raw`, an empty array is allowed; every other type requires at least one non-empty entry.","type":"array","items":{"type":"object","properties":{"campus":{"type":"string","description":"The campus name, lowercased before matching; used when `type` is `campus`."},"concentration":{"type":"string","description":"The concentration's short name; used when `type` is `concentration`."},"department":{"type":"string","description":"The department's short name; used when `type` is `department`."},"enrollment_level":{"type":"string","description":"The enrollment level name; used when `type` is `enrollment_level`."},"program":{"type":"string","description":"The program's short name; used when `type` is `program`."},"school":{"type":"string","description":"The school's short name; used when `type` is `school`. An unknown school returns a 500."},"level":{"type":"string","description":"The student level identifier; used when `type` is `student_level`."},"tags":{"type":"array","description":"Tag names (not tag SIS IDs); used when `type` is `tags`. Unknown names are dropped; if none of the names is found, the call returns 400.","items":{"type":"string"}},"has_all_students":{"type":"boolean","description":"Set to `true` when `type` is `all_students` to target every student."}}}},"action":{"enum":["disallow_register","disallow_drop","hide","warn","reserved_seats","show","add","drop","late_add","late_drop","full_refund","withdraw","change_credit","change_grading_option"],"description":"Action to apply. Visibility and enforcement actions: `hide`, `warn`, `disallow_register`, `disallow_drop`, `reserved_seats`, `show`. Registration-window actions (`add`, `drop`, `late_add`, `late_drop`, `full_refund`, `withdraw`, `change_credit`, `change_grading_option`) are accepted, but their dates aren't saved, so the window never applies. Defaults to `show` when omitted. Any other value, including `instructor_consent` and `department_consent`, is stored as `show` without an error.","type":"string"},"note":{"description":"Text shown with the restriction.","type":"string"},"reserve_capacity":{"description":"Optional number of reserved seats. Read only when `action` is `reserved_seats`; ignored for other actions. Defaults to 0 when missing or non-positive. Must be a number; a string or `null` returns a 500.","type":"integer"},"start_date":{"description":"Optional date the reserved-seat group starts being enforced. Saved only when `action` is `reserved_seats`; ignored for other actions. An unreadable date is stored as empty without an error.","type":"string","format":"date"},"end_date":{"description":"Optional date the reserved-seat group stops being enforced. Saved only when `action` is `reserved_seats`; ignored for other actions. An unreadable date is stored as empty without an error.","type":"string","format":"date"},"rqrmnt_group":{"description":"Optional requirement group identifier, at most 10 characters (a longer value returns a 500). Read only when `action` is `reserved_seats`; ignored for other actions. Used by institutions that integrate with real-time seat-count APIs.","type":"string"}},"required":["section","type","student_sets"]},"SectionRestrictionResponse":{"allOf":[{"type":"object","properties":{"uni_id":{"description":"The restriction's identifier (the `{id}` you sent). Always present in the response.","type":"string"}},"required":["uni_id"]},{"$ref":"#/components/schemas/SectionRestrictionRequest"}]}}},"paths":{"/catalog/section/restriction/{id}":{"post":{"tags":["Catalog Sections"],"parameters":[{"name":"id","in":"path","required":true,"description":"Your identifier for the new restriction (not the section's catalog ID). Must not already be in use.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SectionRestrictionRequest"}}}},"responses":{"200":{"description":"Restriction created. The response always includes `uni_id`, `section`, `type`, `operator`, `action`, `note`, and `student_sets`, with `operator` and `action` as stored (so an unrecognized value comes back as `info` or `show`). When `action` is `reserved_seats`, the response also includes `reserve_capacity`, `start_date`, and `end_date` (empty strings when unset), plus `rqrmnt_group` when it's non-empty. The section's cached data and seat counts are cleared right away.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SectionRestrictionResponse"}}}},"400":{"description":"Validation failure. Errors found while the restriction is saved (the last three causes below) return `message` as a one-element list, for example `\"message\": [\"...\"]`. Nothing is saved.\n\nCommon causes:\n- `{id}` already exists - returns `SectionRestriction with id: {id} already exists`\n- Missing body - returns `no payload provided`\n- Missing `section`, `type`, or `student_sets` - returns `{fields} fields are required but were not found in the payload`\n- Unknown `type` - returns `{type} is not a valid type`\n- Empty `student_sets` for any type other than `raw` (including `raw_pre_req`) - returns `student_sets cannot be empty`\n- The section already has a restriction of this `type`, whatever its action - returns a message starting `A restriction with id` that names the existing restriction\n- None of the names in a `tags` set exists - returns a message starting `One or multiple tags with name`. A list with at least one known name succeeds and drops the unknown names.\n- A campus, concentration, department, enrollment level, program, or student level in `student_sets` doesn't exist - returns a message ending `matching query does not exist.`"},"401":{"description":"Missing or invalid Bearer token.\n\nCommon causes:\n- Auth failure"},"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"}}}}}},"404":{"description":"Target section not found.\n\nCommon causes:\n- Unknown section - returns `Course section with id:{section} does not exist`"},"500":{"description":"Unhandled server error. Nothing is saved.\n\nCommon causes:\n- A `school` in `student_sets` doesn't exist\n- `reserve_capacity` is a string or `null` on a `reserved_seats` restriction\n- `rqrmnt_group` is longer than 10 characters\n- More than one section carries the `section` ID"}}}}}}
```

#### What happens after the call

* The restriction is created right away under your `{id}`, which is the restriction's identifier, not the section's.
* It applies from each student's next catalog view, registration, or drop. Students already enrolled stay enrolled.

#### Notes

{% hint style="warning" %}
**Unrecognized `action` or `operator` values are saved without an error.** An unknown action is stored as `show` and an unknown operator as `info`, and neither restricts anyone. That includes `instructor_consent` and `department_consent`, which this endpoint doesn't support. Check both values before sending.
{% endhint %}

* **Registration-window actions don't take effect here.** `add`, `drop`, `late_add`, `late_drop`, `full_refund`, `withdraw`, `change_credit`, and `change_grading_option` are accepted, but their dates aren't saved, so the window never applies.
* **`neq` applies to everyone outside the set.** To make a section honors-only, send `action: hide`, `operator: neq`, and `tags: ["honors"]`. Students with no student set at all aren't matched, so they still see the section.
* **Restrictions with the same action and operator combine.** Two `hide` / `neq` restrictions on one section (for example honors students and one program) hide it only from students in neither set.
* **One restriction per section and type.** To change a restriction, delete it and create a new one.
* **What each student set names must already exist.** Programs, departments, and concentrations are matched on short name, tags on name. A tag list keeps only the tags it finds. An unknown school returns a 500 rather than a 400.
* **`raw` and `raw_pre_req` take no rule text.** Put any text for students in `note`.
* **For `reserved_seats`, check the field limits.** `rqrmnt_group` is at most 10 characters, `reserve_capacity` must be a number, and an unreadable date is stored as empty without an error.

#### Related APIs

* [`DELETE /catalog/section/restriction/{id}`](/stellic-partner-api/catalog-sections/remove-a-section-restriction.md) to remove the restriction.
* [`POST /tag/{tag_sis_id}`](/stellic-partner-api/student/create-a-student-tag-definition.md) to create the tags a `tags` restriction uses.
* [`POST /catalog/section/constraint/{sis_id}`](/stellic-partner-api/catalog-sections/create-a-section-constraint.md) to gate reserved seats on a requirement group instead of a student set.
* [`PUT /catalog/section/{id}`](/stellic-partner-api/catalog-sections/update-section-enrollment-caps.md) to change the section's seat and waitlist counts.
