REST API wrappers for the Alachisoft NCache SDK that expose the full NCache feature set over HTTP — so any language or platform can interact with your NCache cluster without requiring the native .NET SDK.
Two independent services are provided:
| Service | NuGet Package | Default Port | Features |
|---|---|---|---|
| Enterprise | Alachisoft.NCache.SDK |
5000 | CRUD, Bulk, Tags, Groups, Expiry, Admin |
| OpenSource | Alachisoft.NCache.OpenSource.SDK |
5001 | CRUD, Bulk, Expiry, Admin |
- Architecture
- Prerequisites
- Getting Started
- Configuration
- Authentication
- API Reference
- Request / Response Format
- Expiry Options
- Client Examples
- Swagger / OpenAPI
- Security Considerations
- Project Structure
- Contributing
- License
┌──────────────────────────────────────────────────────────┐
│ Any HTTP Client │
│ (browser, Python, Java, Go, curl…) │
└─────────────────────────┬────────────────────────────────┘
│ HTTP + JWT Bearer
┌───────────────┴───────────────┐
▼ ▼
┌─────────────────────┐ ┌─────────────────────────┐
│ NCache Enterprise │ │ NCache OpenSource │
│ REST API (:5000) │ │ REST API (:5001) │
│ ASP.NET Core 8 │ │ ASP.NET Core 8 │
│ JWT Auth │ │ JWT Auth │
│ Connection Pool │ │ Connection Pool │
└──────────┬──────────┘ └───────────┬─────────────┘
│ Alachisoft.NCache.SDK │ Alachisoft.NCache.OpenSource.SDK
▼ ▼
┌──────────────────────────────────────────────────────────┐
│ NCache Cluster │
│ (Enterprise or OpenSource) │
└──────────────────────────────────────────────────────────┘
Connection pooling: When a client calls POST /api/auth/connect, the service establishes a live ICache connection and stores it in a server-side ConcurrentDictionary. The returned JWT contains a connectionId claim that maps back to this connection. No credentials are stored in the token.
- .NET 8 SDK
- A running NCache server (Enterprise or OpenSource edition)
- NCache client connectivity from the machine running this service
git clone https://github.com/zohaibpk/NCacheRestAPI.git
cd NCacheRestAPIEdit appsettings.json in the relevant project folder and replace the placeholder secret:
{
"Jwt": {
"Secret": "your-strong-secret-at-least-32-characters-long",
"Issuer": "NCache.Enterprise.RestAPI",
"Audience": "NCache.Enterprise.RestAPI.Clients"
}
}Important: Use a randomly generated secret of at least 32 characters. Never commit real secrets to source control — use environment variables or a secrets manager in production.
You can also set it via environment variable at runtime:
# Linux / macOS
export Jwt__Secret="your-strong-secret-here"
# Windows (PowerShell)
$env:Jwt__Secret = "your-strong-secret-here"# Enterprise REST API
cd src/NCache.Enterprise.RestAPI
dotnet run
# OpenSource REST API
cd src/NCache.OpenSource.RestAPI
dotnet runThe service will start on http://localhost:5000 (Enterprise) or http://localhost:5001 (OpenSource).
- Landing page:
http://localhost:5000/ - Swagger UI:
http://localhost:5000/swagger
| Key | Description | Default |
|---|---|---|
Jwt:Secret |
HMAC-SHA256 signing key (min 32 chars) | (must be set) |
Jwt:Issuer |
JWT issuer claim | NCache.Enterprise.RestAPI |
Jwt:Audience |
JWT audience claim | NCache.Enterprise.RestAPI.Clients |
NCache connection parameters (cache name, server address, port) are supplied per request via the connect endpoint and are not configured in appsettings.
All endpoints except POST /api/auth/connect require a JWT bearer token.
POST /api/auth/connect
Content-Type: application/json
{
"cacheName": "MyCache",
"serverAddress": "192.168.1.100",
"serverPort": 9800,
"ncacheUsername": "optional-if-security-enabled",
"ncachePassword": "optional-if-security-enabled",
"tokenExpiryHours": 8
}Response:
{
"success": true,
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresAt": "2026-04-27T12:00:00Z",
"cacheName": "MyCache",
"serverAddress": "192.168.1.100",
"serverPort": 9800
}
}Include the token on every subsequent request:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
DELETE /api/auth/disconnect
Authorization: Bearer <token>This disposes the server-side NCache connection and invalidates the session.
All responses share a common JSON envelope:
{ "success": true, "data": { ... }, "error": null }
{ "success": false, "data": null, "error": "Descriptive message" }| Code | Meaning |
|---|---|
200 |
Success |
201 |
Item created (Add) |
400 |
Validation error |
401 |
Missing or invalid/expired token |
404 |
Key not found |
409 |
Key already exists (Add) |
503 |
Cannot reach the NCache server |
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/api/auth/connect |
None | Connect to NCache, get JWT |
DELETE |
/api/auth/disconnect |
Bearer | Disconnect and invalidate token |
GET |
/api/auth/status |
Bearer | Current connection metadata |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/cache/{key} |
Bearer | Get item by key |
POST |
/api/cache |
Bearer | Add item (409 if key exists) |
PUT |
/api/cache |
Bearer | Insert / upsert item |
DELETE |
/api/cache/{key} |
Bearer | Remove item |
HEAD |
/api/cache/{key} |
Bearer | Key existence check (no body) |
POST |
/api/cache/{key}/get-and-remove |
Bearer | Atomic get + remove |
{
"key": "user:42",
"value": { "id": 42, "name": "Alice", "role": "admin" },
"expiry": {
"type": "Absolute",
"duration": "01:00:00"
},
"tags": ["active", "premium"],
"group": "users",
"subGroup": "premium"
}
tags,group, andsubGroupare Enterprise-only fields and are silently ignored by the OpenSource service.
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/api/cache/bulk/get |
Bearer | Get multiple items |
POST |
/api/cache/bulk/add |
Bearer | Add multiple items |
PUT |
/api/cache/bulk/insert |
Bearer | Upsert multiple items |
POST |
/api/cache/bulk/remove |
Bearer | Remove multiple items |
{ "keys": ["user:1", "user:2", "user:3"] }{
"success": true,
"data": {
"items": {
"user:1": { "id": 1, "name": "Alice" },
"user:2": null,
"user:3": { "id": 3, "name": "Charlie" }
},
"foundCount": 2,
"missCount": 1
}
}{
"items": [
{
"key": "product:10",
"value": { "name": "Widget", "price": 9.99 },
"expiry": { "type": "Sliding", "duration": "00:30:00" },
"tags": ["electronics"]
},
{
"key": "product:11",
"value": { "name": "Gadget", "price": 29.99 }
}
]
}| Method | Path | Description |
|---|---|---|
POST |
/api/cache/tags/keys |
Get keys matching the given tags |
POST |
/api/cache/tags/items |
Get items matching the given tags |
POST |
/api/cache/tags/remove |
Remove items matching the given tags |
{
"tags": ["electronics", "sale"],
"searchOption": "Any"
}searchOption values:
Any— items matching at least one of the tagsAll— items matching all of the tags
| Method | Path | Description |
|---|---|---|
POST |
/api/cache/groups/items |
Get all items in a group |
POST |
/api/cache/groups/keys |
Get all keys in a group |
POST |
/api/cache/groups/remove |
Remove all items in a group |
{
"group": "users",
"subGroup": "premium"
}| Method | Path | Description |
|---|---|---|
GET |
/api/cache/admin/stats |
Cache name, server, and item count |
GET |
/api/cache/admin/count |
Item count only |
GET |
/api/cache/admin/keys?skip=0&take=100 |
Paginated key list |
POST |
/api/cache/admin/clear |
Remove all items (irreversible) |
Include an expiry object on any Add or Insert request:
"expiry": {
"type": "Absolute",
"duration": "01:30:00"
}| Type | Behaviour |
|---|---|
None |
Item never expires (default if expiry is omitted) |
Absolute |
Expires after the specified duration from insertion time |
Sliding |
Expiry window resets on each access |
Duration format: HH:MM:SS — e.g. "00:30:00" for 30 minutes, "08:00:00" for 8 hours.
The value field accepts any valid JSON — objects, arrays, strings, numbers, booleans, or null.
// Object
"value": { "id": 1, "name": "Alice" }
// Array
"value": [1, 2, 3]
// Primitive
"value": "hello world"
// Number
"value": 42.5Full working client code is available for the following languages — viewable interactively on the service's landing page (http://localhost:5000/) or as Markdown files in each project's docs/ folder:
| Language | File |
|---|---|
| C# | docs/csharp.md |
| Java | docs/java.md |
| Python | docs/python.md |
| JavaScript / Node.js | docs/javascript.md |
| PHP | docs/php.md |
| Go | docs/go.md |
| cURL | docs/curl.md |
# 1. Connect and capture the token
TOKEN=$(curl -s -X POST http://localhost:5000/api/auth/connect \
-H "Content-Type: application/json" \
-d '{"cacheName":"MyCache","serverAddress":"localhost","serverPort":9800}' \
| python3 -c "import sys,json; print(json.load(sys.stdin)['data']['token'])")
# 2. Insert an item with 1-hour absolute expiry
curl -s -X PUT http://localhost:5000/api/cache \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"key":"user:1","value":{"name":"Alice"},"expiry":{"type":"Absolute","duration":"01:00:00"}}'
# 3. Retrieve the item
curl -s http://localhost:5000/api/cache/user:1 \
-H "Authorization: Bearer $TOKEN" | python3 -m json.tool
# 4. Disconnect
curl -s -X DELETE http://localhost:5000/api/auth/disconnect \
-H "Authorization: Bearer $TOKEN"Both services expose a full interactive Swagger UI:
- Enterprise:
http://localhost:5000/swagger - OpenSource:
http://localhost:5001/swagger
Click Authorize in Swagger UI, paste Bearer <token> (obtained from the connect endpoint), and all endpoints become directly testable from the browser.
The OpenAPI JSON spec is available at /swagger/v1/swagger.json for import into Postman, Insomnia, or any other REST client.
| Concern | Recommendation |
|---|---|
| JWT Secret | Use a randomly generated string of 32+ characters. Rotate periodically. |
| Secret storage | Use environment variables or a secrets manager (Azure Key Vault, AWS Secrets Manager, etc.) — never commit to source control. |
| HTTPS | Enable HTTPS / TLS termination in production. The pipeline includes UseHttpsRedirection. |
| Token expiry | Default is 8 hours. Set shorter expiry for sensitive environments via tokenExpiryHours in the connect request. |
| NCache credentials | Supplied only at connect time. They are used once to establish the ICache connection and are never stored in the JWT or in memory after that. |
| Network | Place the REST API behind an API gateway or firewall — do not expose NCache ports directly to the internet. |
ncache-rest-api/
├── ncache-rest-api.slnx
├── README.md
├── LICENSE
├── .gitignore
└── src/
├── NCache.Common/ # Shared library
│ ├── DTOs/
│ │ ├── Requests/ # ConnectRequest, CacheItemRequest, Bulk*, Tag*, Group*
│ │ └── Responses/ # ApiResponse<T>, ConnectResponse, CacheItemResponse, …
│ └── Models/ # ExpiryOptions, ExpiryType, TagSearchOption
│
├── NCache.Enterprise.RestAPI/ # Enterprise SDK service
│ ├── Controllers/
│ │ ├── AuthController.cs # Connect / Disconnect / Status
│ │ ├── CacheController.cs # CRUD + Get-and-Remove
│ │ ├── BulkController.cs # Bulk Get / Add / Insert / Remove
│ │ ├── TagsController.cs # Tag-based operations
│ │ ├── GroupsController.cs # Group-based operations
│ │ ├── AdminController.cs # Stats / Count / Keys / Clear
│ │ ├── DocsController.cs # Serves Markdown docs
│ │ └── HomeController.cs # Landing page
│ ├── Services/
│ │ ├── IJwtService / JwtService # Token generation & validation
│ │ ├── IConnectionPool / ConnectionPool # ICache lifecycle management
│ │ └── ICacheService / CacheService # NCache operation wrappers
│ ├── Models/
│ │ └── ConnectionEntry.cs # Internal connection record
│ ├── docs/ # Markdown client docs (8 languages)
│ ├── wwwroot/index.html # Bootstrap 5 landing page
│ ├── Program.cs
│ └── appsettings.json
│
└── NCache.OpenSource.RestAPI/ # OpenSource SDK service
├── Controllers/ # Auth, Cache, Bulk, Admin, Docs, Home
├── Services/ # Same structure as Enterprise
├── docs/ # Same language docs
├── wwwroot/index.html
├── Program.cs
└── appsettings.json
Contributions are welcome. Please open an issue to discuss a change before submitting a pull request.
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Commit your changes
- Open a pull request against
master
- The two SDK packages have meaningfully different API surfaces. Enterprise has
WriteThruOptions/ReadThruOptionson most calls; OpenSource does not. Keep both services in sync where the API is identical. - Values are stored as UTF-8 JSON bytes in NCache. All JSON types (object, array, string, number, bool, null) are supported as cache values.
TagSearchOptionsenum is in theAlachisoft.NCache.Clientnamespace (notRuntime.Caching).