Folder structure and routing
Each subfolder under endpoints/ corresponds to an endpoint type. The folder name within each type becomes the endpoint name in the API URL. Portway watches these folders and reloads configuration when files change.
In practice this means Portway derives your API routes from the endpoints/ folder hierarchy, so there is no route registration step at all. When you want different naming, the Namespace and DisplayName attributes let you override the derived route; that's an advanced setup covered further down.
Directory layout
PortwayApi/
├── appsettings.json
├── web.config
├── *.db
├── log/
├── tokens/
├── environments/
│ ├── settings.json
│ ├── dev/
│ │ └── settings.json
│ ├── test/
│ │ └── settings.json
│ └── prod/
│ └── settings.json
└── endpoints/
├── SQL/
│ └── Products/
│ └── entity.json
├── Proxy/
│ ├── Accounts/
│ │ └── entity.json
│ └── SalesOrder/
│ └── entity.json
├── Webhooks/
│ └── entity.json
├── Files/
│ ├── CustomerData/
│ │ └── entity.json
│ └── Images/
│ └── entity.json
└── Static/
└── Countries/
└── entity.jsonRoute patterns
| Endpoint type | Folder path | URL pattern |
|---|---|---|
| SQL | endpoints/SQL/{Name}/entity.json |
/api/{env}/{Name} |
| Proxy | endpoints/Proxy/{Name}/entity.json |
/api/{env}/{Name} |
| Composite | endpoints/Proxy/{Name}/entity.json (Type: Composite) |
/api/{env}/composite/{Name} |
| Webhook | endpoints/Webhooks/{Namespace}/{Name}/entity.json |
/api/{env}/{Namespace}/{Name}/{id} |
| File | endpoints/Files/[{Namespace}/]{Name}/entity.json |
/api/{env}/files/[{Namespace}/]{Name} |
| Static | endpoints/Static/{Name}/entity.json |
/api/{env}/{Name} |
The endpoint name in the URL is case-sensitive and matches the folder name exactly.
The QUERY method
Sometimes a read needs more than a URL can comfortably carry. When your filters grow long, or you would simply rather not see query details sitting in access logs, the QUERY method (described in RFC 10008) offers a friendly alternative. It behaves much like a GET, except your criteria travel in the request body as JSON.
QUERY is a read, and only a read. It is safe and idempotent, so Portway routes it through the same code that serves GET (SQL selects, static content, and proxied reads) and never through anything that writes. Because it stays safe, the response is cacheable too, and Portway folds your request body into the cache key so that two different queries never share a cached answer.
You can opt an endpoint into QUERY by adding it to AllowedMethods:
{
"DatabaseObjectName": "StockLevels",
"AllowedMethods": ["QUERY"],
"AllowedEnvironments": ["prod"]
}A request then carries its criteria as JSON. Both the bare and $-prefixed OData field names are accepted, so you can reach for whichever feels natural:
QUERY /api/prod/Inventory/StockLevels
Content-Type: application/json
Authorization: Bearer <token>
{
"select": "Sku,Warehouse,Quantity",
"filter": "Quantity gt 0 and Warehouse eq 'AMS'",
"orderby": "Quantity desc",
"top": 50
}The response mirrors the equivalent GET, including pagination headers and an optional Content-Location that points at the GET URL which would return the same results.
Note: QUERY expects a JSON body, so please remember to include
Content-Type: application/json. A request without it is answered with415 Unsupported Media Type, which is really just a gentle nudge rather than a hard failure.
SQL, Proxy, and Static endpoints all treat QUERY as a read. Composite and Webhook endpoints are about orchestration and writes, so they kindly decline QUERY with 405 Method Not Allowed.
Folder permissions
Grant the IIS Application Pool identity read/write access to the deployment directory:
# ApplicationPoolIdentity
icacls "C:\Apps\Portway" /grant "IIS AppPool\PortwayAppPool:(F)" /T /C
# Custom service account
icacls "C:\Apps\Portway" /grant "DOMAIN\SVC_PORTWAY:(F)" /T /C| Folder | Minimum permission | Reason |
|---|---|---|
log/ |
Read/Write | Log file creation and rotation |
tokens/ |
Read/Write | Token file management |
environments/ |
Read | Configuration reads |
endpoints/ |
Read | Configuration reads |
| Root | Read/Write | auth.db and temporary files |
WARNING
Do not expose the deployment directory via web browsing. Verify that web.config disables directory listing.
Portway