{"templateId":"markdown","sharedDataIds":{},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Paths","siteUrl":"https://developers.frontegg.com/","llmstxt":{"title":"Frontegg Developer Documentation","description":"Authentication, authorization, and user management for Customer Identity, plus Agen for SaaS and Agen for Work. Guides, SDKs, and API references.","sections":[{"title":"Customer Identity (CIAM)","description":"Auth, SSO, SCIM, entitlements, and user management — guides, SDKs, and APIs.","includeFiles":["ciam/**/*.md"],"excludeFiles":[]},{"title":"Agen for SaaS","description":"Agentic access and authorization for SaaS products.","includeFiles":["agen-for-saas/**/*.md"],"excludeFiles":[]},{"title":"Agen for Work","description":"Agentic access and authorization for internal and workforce use.","includeFiles":["agen-for-work/**/*.md"],"excludeFiles":[]},{"title":"Platform","description":"Shared platform overview.","includeFiles":["platform/**/*.md"],"excludeFiles":[]}],"excludeFiles":["internal-docs/**","ciam/guides/env-settings/inject-client-ip.md","CLAUDE.md",".claude/**","**/images/**"],"hide":false}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"paths","__idx":0},"children":["Paths"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Organize your path definitions within this folder.  You will reference your paths from your main ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["openapi.yaml"]}," entrypoint file."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["It may help you to adopt some conventions:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["path separator token (e.g. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["_"]},") or subfolders"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["path parameter (e.g. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{example}"]},")"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["file-per-path or file-per-operation"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["There are different benefits and drawbacks to each decision."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can adopt any organization you wish.  We have some tips for organizing paths based on common practices."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"each-path-in-a-separate-file","__idx":1},"children":["Each path in a separate file"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use a predefined \"path separator\" and keep all of your path files in the top level of the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paths"]}," folder."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"├── echo.yaml\n├── path-item-with-examples.yaml\n├── path-item.yaml\n└── users_{username}.yaml\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Redocly recommends using the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["_"]}," character for this case."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In addition, Redocly recommends placing path parameters within ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{}"]}," curly braces if you adopt this style."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"motivations","__idx":2},"children":["Motivations"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Quickly see a list of all paths.  Many people think in terms of the \"number\" of \"endpoints\" (paths), and not the \"number\" of \"operations\" (paths * http methods)."]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Only the \"file-per-path\" option is semantically correct with the OpenAPI Specification 3.0.2.  However, Redocly's openapi-cli will build valid bundles for any of the other options too."]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"drawbacks","__idx":3},"children":["Drawbacks"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["This may require multiple definitions per http method within a single file."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["It requires settling on a path separator (that is allowed to be used in filenames) and sticking to that convention."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"each-operation-in-a-separate-file","__idx":4},"children":["Each operation in a separate file"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You may also place each operation in a separate file."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In this case, if you want all paths at the top-level, you can concatenate the http method to the path name.  Similar to the above option, you can"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"files-at-top-level-of-paths","__idx":5},"children":["Files at top-level of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paths"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You may name your files with some concatenation for the http method. For example, following a convention such as: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["<path with allowed separator>-<http-method>.yaml"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"motivations-1","__idx":6},"children":["Motivations"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Quickly see all operations without needing to navigate subfolders."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"drawbacks-1","__idx":7},"children":["Drawbacks"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Adopting an unusual path separator convention, instead of using subfolders."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"use-subfolders-to-mirror-api-path-structure","__idx":8},"children":["Use subfolders to mirror API path structure"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Example:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"GET /customers\n\n/paths/customers/get.yaml\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In this case, the path id defined within subfolders which mirror the API URL structure."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Example with path parameter:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"GET /customers/{id}\n\n/paths/customers/{id}/get.yaml\n"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"motivations-2","__idx":9},"children":["Motivations"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["It matches the URL structure."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["It is pretty easy to reference:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"paths:\n  '/customers/{id}':\n    get:\n      $ref: ./paths/customers/{id}/get.yaml\n    put:\n      $ref: ./paths/customers/{id}/put.yaml\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"drawbacks-2","__idx":10},"children":["Drawbacks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If you have a lot of nested folders, it may be confusing to reference your schemas."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Example"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"file: /paths/customers/{id}/timeline/{messageId}/get.yaml\n\n# excerpt of file\n    headers:\n      Rate-Limit-Remaining: \n        $ref: ../../../../../components/headers/Rate-Limit-Remaining.yaml\n\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Notice the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["../../../../../"]}," in the ref which requires some attention to formulate correctly.  While openapi-cli has a linter which suggests possible refs when there is a mistake, this is still a net drawback for APIs with deep paths."]}]},"headings":[{"value":"Paths","id":"paths","depth":1},{"value":"Each path in a separate file","id":"each-path-in-a-separate-file","depth":2},{"value":"Motivations","id":"motivations","depth":4},{"value":"Drawbacks","id":"drawbacks","depth":4},{"value":"Each operation in a separate file","id":"each-operation-in-a-separate-file","depth":2},{"value":"Files at top-level of paths","id":"files-at-top-level-of-paths","depth":3},{"value":"Motivations","id":"motivations-1","depth":4},{"value":"Drawbacks","id":"drawbacks-1","depth":4},{"value":"Use subfolders to mirror API path structure","id":"use-subfolders-to-mirror-api-path-structure","depth":3},{"value":"Motivations","id":"motivations-2","depth":4},{"value":"Drawbacks","id":"drawbacks-2","depth":4}],"frontmatter":{"seo":{"title":"Paths"}},"lastModified":"2025-11-04T13:25:50.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/ciam/api/paths/readme","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}