Appearance
API Reference
Complete reference for the Solenoid Meter API v1.
Base URL
https://api.solenoid.systemsAll endpoints require authentication with a Bearer token. See Authentication.
Endpoints
GET /v1/meter/balance
Get the current balance for the authenticated user.
Request:
bash
curl -X GET https://api.solenoid.systems/v1/meter/balance \
-H "Authorization: Bearer sm_your_api_key_here"Success Response (200):
json
{
"balance": 100,
"user_id": "usr_abc123"
}Fields:
balance(number): Current credit balanceuser_id(string): Unique user identifier
Error Responses:
401- Invalid or missing API key
POST /v1/meter/deduct
Atomically deduct credits from the user's balance.
This operation is atomic - if the balance is insufficient, no deduction occurs and a 402 response is returned with the current balance.
Request:
bash
curl -X POST https://api.solenoid.systems/v1/meter/deduct \
-H "Authorization: Bearer sm_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"amount": 1}'Request Body:
json
{
"amount": 1
}Fields:
amount(number, required): Number of credits to deduct. Must be positive.
Success Response (200):
json
{
"balance": 99,
"user_id": "usr_abc123"
}Fields:
balance(number): Remaining balance after deductionuser_id(string): Unique user identifier
Error Responses:
402 Payment Required - Insufficient balance:
json
{
"error": {
"code": "insufficient_balance",
"message": "Insufficient balance for this operation"
},
"balance": 0,
"user_id": "usr_abc123"
}The current balance is included in the error response so you can prompt the user to add credits.
400 Bad Request - Invalid amount:
json
{
"error": {
"code": "invalid_request",
"message": "Amount must be a positive number"
}
}401 Unauthorized - Invalid or missing API key
POST /v1/meter/refill
Add credits to the user's balance.
Request:
bash
curl -X POST https://api.solenoid.systems/v1/meter/refill \
-H "Authorization: Bearer sm_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"amount": 100}'Request Body:
json
{
"amount": 100
}Fields:
amount(number, required): Number of credits to add. Must be positive.
Success Response (200):
json
{
"balance": 100,
"user_id": "usr_abc123"
}Fields:
balance(number): New balance after refilluser_id(string): Unique user identifier
Error Responses:
400 Bad Request - Invalid amount:
json
{
"error": {
"code": "invalid_request",
"message": "Amount must be a positive number"
}
}401 Unauthorized - Invalid or missing API key
POST /v1/keys/rotate
Rotate your API key. The old key is immediately invalidated.
Request:
bash
curl -X POST https://api.solenoid.systems/v1/keys/rotate \
-H "Authorization: Bearer sm_old_key_here"Success Response (200):
json
{
"key": "sm_new_key_here"
}Fields:
key(string): Your new API key. Store this securely - the old key no longer works.
Error Responses:
401 Unauthorized - Invalid or missing API key
Response Format
All responses are flat JSON objects (no envelope wrapper).
Success responses contain the requested data directly.
Error responses include an error object with:
code(string): Machine-readable error codemessage(string): Human-readable error description
Some errors include additional context fields (e.g., balance in insufficient balance errors).
Rate Limits
Free tier: 10 requests per second
Pro tier: Higher limits, no throttling on production workloads
Rate limit exceeded responses return 429 Too Many Requests:
json
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded"
}
}Atomicity Guarantees
All operations are atomic, powered by Cloudflare Durable Objects:
- Deduct: Balance check and deduction happen atomically. No race conditions.
- Refill: Credit addition is atomic.
- Concurrent requests: Serialized per user. Correct balance guaranteed.
This eliminates double-spend issues and ensures consistency even under high concurrency.