Documentation
Everything you need to integrate SOAPless into your application.
On This Page
Jump to setup, method policies, testing, API keys, and troubleshooting.
Start in 3 steps
Register a WSDL, issue an API key, and make the first JSON request.
Choose GET vs POST
Understand service defaults, per-operation overrides, and when GET is exposed.
Use exact endpoint shapes
Jump straight to path format, headers, status codes, and OpenAPI-related behavior.
Quick Start
Get up and running with SOAPless in three steps.
What you get after setup
A stable account-scoped endpoint, JSON request and response handling, API key auth, and optional GET support for read-style operations.
Step 1: Register Your WSDL Service
Add your SOAP service in the dashboard. Provide the WSDL URL and optional SOAP credentials. SOAPless will parse the WSDL and generate REST endpoints automatically.
Step 2: Create an API Key
Generate an API key from the API Keys page. Copy it immediately — the full key is shown only once.
Step 3: Make Your First Request
Call your new REST endpoint. In the default configuration, POST with JSON works:
curl -X POST https://soapless.miravy.com/api/v1/ab12cd34ef/my-service/GetUser \
-H "Content-Type: application/json" \
-H "X-API-Key: sl_live_your_api_key_here" \
-d '{"userId": 42}'GET can also be enabled automatically for read-style operations, or enabled manually per operation on paid plans:
curl "https://soapless.miravy.com/api/v1/ab12cd34ef/my-service/GetSum?a=2&b=3" \
-H "X-API-Key: sl_live_your_api_key_here"Authentication
All API requests must include your API key in the X-API-Key header.
POST /api/v1/{accountId}/{serviceSlug}/{operationName} HTTP/1.1
Host: soapless.miravy.com
Content-Type: application/json
X-API-Key: sl_live_your_api_key_hereGET requests use the same X-API-Key header and omit the JSON body.
API keys are scoped to your account and can be created, rotated, or revoked at any time from the dashboard. We recommend using separate keys for each environment (development, staging, production).
Upstream SOAP authentication
If the SOAP service itself requires authentication, you can configure it per service in the dashboard. HTTP Basic Auth is available on all plans, WS-Security on Starter and above, and custom outbound headers on Pro.
- HTTP Basic Auth: for upstream services that expect a standard username and password over HTTP.
- WS-Security: for SOAP services that expect a UsernameToken in the SOAP header.
- Custom header: for proprietary tokens or gateway headers that must be sent with each outbound request.
Stored SOAP credentials are encrypted at rest. In the edit screen, leaving credential fields blank keeps the current stored value.
Making Requests
SOAPless exposes each SOAP operation as a REST endpoint:
POST /api/v1/{accountId}/{serviceSlug}/{operationName}GET /api/v1/{accountId}/{serviceSlug}/{operationName}GET is available for read-style operations with simple query-safe inputs, or when you explicitly enable GET for that operation in the dashboard on a paid plan.
- accountId: Your stable public Account ID from Settings (e.g.,
ab12cd34ef). - serviceSlug: The slug you assigned when registering your WSDL service (e.g.,
my-erp). - operationName: The SOAP operation name from the WSDL (e.g.,
GetUser).
Send JSON in the request body. SOAPless converts it to the appropriate SOAP XML envelope, calls the upstream service, and returns the response as JSON.
- POST is supported by default. It can be disabled per operation with a manual GET-only policy.
- GET can be added automatically for read-style operations or manually per operation on Starter and Pro.
- GET additionally requires a read-like operation name such as
GetUser,ListOrders, orGetSum. - GET additionally requires every input field to be a top-level primitive: string, number, integer, or boolean.
- Manual per-operation method policies are preserved across WSDL refresh for matching operation names.
- If an operation has nested objects or arrays, use POST.
Method Policies In The Dashboard
Each service has a default method strategy, and each operation can optionally override it.
- Inherit: Use the service default.
- POST: Force POST only for that operation.
- GET: Force GET only when the input schema is query-safe.
- GET + POST: Expose both methods when the input schema is query-safe.
- When both methods are available, dashboard examples prefer GET for read-like operations and POST otherwise.
- Operation-level policies are available on Starter and Pro plans.
- Changing a policy refreshes the API Explorer and OpenAPI output immediately.
Testing Operations
The service detail page includes a session-authenticated test panel for trying operations without creating an API key first.
- Example JSON is generated from the operation schema to help you start with a valid request.
- When an operation supports both GET and POST, the test panel lets you switch between them before executing.
- SOAP faults are normalized into readable messages instead of raw object dumps.
- The test panel is for manual verification. Production clients should use the generated REST endpoints with API keys.
Response Format
Successful responses return a JSON object with result and meta fields:
{
"result": {
"id": 42,
"name": "Alice Johnson",
"email": "alice@acme.com",
"department": "Engineering"
},
"meta": {
"service": "my-erp",
"operation": "GetUser",
"latencyMs": 245
}
}Error Format
Error responses return a consistent JSON structure:
{
"error": {
"type": "VALIDATION_ERROR",
"code": 400,
"message": "Missing required field: userId"
}
}The type field is a machine-readable error category. The message field provides a human-readable description. See the API Reference for a full list of error types.
Rate Limits
Usage limits are tracked at the account level, not per API key. Free accounts receive HTTP 429 after reaching the monthly cap, while paid plans can continue and incur overage billing.
| Plan | Monthly Limit | Rate Limit | Overage |
|---|---|---|---|
| Free | 100 calls | 10 req/min | Blocked |
| Starter ($29/mo) | 10,000 calls | No limit | $0.01/call |
| Pro ($99/mo) | 100,000 calls | No limit | $0.01/call |
Rate limit headers are included in every response:
X-RateLimit-Limit: 10000
X-RateLimit-Remaining: 9542
X-RateLimit-Reset: 2026-04-01T00:00:00ZAuthentication Details
SOAPless uses API keys for authentication. Here is everything you need to know about creating and using them.
Getting Your API Key
Including the API Key
Pass your key in the X-API-Key header on every request. Both proxy calls and the OpenAPI spec endpoint accept this header.
GET /api/services/{id}/openapi HTTP/1.1
Host: soapless.miravy.com
X-API-Key: sl_live_your_api_key_hereKey Security Best Practices
- Store keys in environment variables, never in source code.
- Use separate keys per environment (dev, staging, prod).
- Rotate keys periodically from the dashboard.
- Revoke compromised keys immediately.
curl Examples
Common operations you can perform from the command line or CI pipelines.
Proxy Call
curl -X POST https://soapless.miravy.com/api/v1/ab12cd34ef/my-erp/GetUser \
-H "Content-Type: application/json" \
-H "X-API-Key: sl_live_abc123" \
-d '{"userId": 42}'Fetch OpenAPI Spec
Download the auto-generated OpenAPI 3.0 spec for a service (requires a paid plan).
curl -H "X-API-Key: sl_live_abc123" \
https://soapless.miravy.com/api/services/{service-id}/openapi \
-o my-service-openapi.jsonInspect Rate Limit Headers
curl -v -X POST https://soapless.miravy.com/api/v1/ab12cd34ef/my-erp/GetUser \
-H "Content-Type: application/json" \
-H "X-API-Key: sl_live_abc123" \
-d '{"userId": 42}' 2>&1 | grep -i x-ratelimitError Handling
SOAPless returns consistent error JSON. Here is how to handle the most common errors in your code.
401 Unauthorized
Your API key is missing, invalid, or revoked. Double-check the X-API-Key header and ensure the key has not been revoked in the dashboard.
{
"error": {
"type": "auth",
"code": "INVALID_API_KEY",
"message": "Invalid API key"
}
}429 Too Many Requests
You have exceeded your monthly quota (Free plan) or per-minute rate limit. Check the X-RateLimit-Reset header to know when the current period resets. Free accounts are blocked at the monthly cap, while paid plans continue with overage billing.
{
"error": {
"type": "rate_limit",
"code": "MONTHLY_LIMIT_EXCEEDED",
"message": "Monthly API call limit exceeded (100 calls for free plan)."
}
}502 Bad Gateway
The upstream SOAP service is unreachable or returned a SOAP Fault. This is not a SOAPless issue. Verify the SOAP service is up and check the error.detail field for the original fault message.
{
"error": {
"type": "upstream",
"code": "SOAP_FAULT",
"message": "Upstream SOAP service returned a fault",
"detail": "Server was unable to process request: timeout"
}
}Retry Strategy
async function callWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const res = await fetch(url, options);
if (res.status === 429) {
const resetAt = res.headers.get("X-RateLimit-Reset");
const waitMs = resetAt
? new Date(resetAt).getTime() - Date.now()
: 1000 * Math.pow(2, attempt);
await new Promise((r) => setTimeout(r, waitMs));
continue;
}
if (res.status === 502 && attempt < maxRetries - 1) {
await new Promise((r) => setTimeout(r, 1000 * Math.pow(2, attempt)));
continue;
}
return res;
}
throw new Error("Max retries exceeded");
}SDK Examples
Code snippets for calling the SOAPless proxy from popular languages.
JavaScript / TypeScript
const response = await fetch(
"https://soapless.miravy.com/api/v1/ab12cd34ef/my-erp/GetUser",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": process.env.SOAPLESS_API_KEY,
},
body: JSON.stringify({ userId: 42 }),
}
);
if (!response.ok) {
const err = await response.json();
throw new Error(err.error.message);
}
const { result, meta } = await response.json();
console.log(result); // { id: 42, name: "Alice Johnson", ... }
console.log(meta); // { latencyMs: 245, ... }Python
import os
import requests
response = requests.post(
"https://soapless.miravy.com/api/v1/ab12cd34ef/my-erp/GetUser",
headers={
"Content-Type": "application/json",
"X-API-Key": os.environ["SOAPLESS_API_KEY"],
},
json={"userId": 42},
timeout=30,
)
response.raise_for_status()
data = response.json()
print(data["result"]) # {'id': 42, 'name': 'Alice Johnson', ...}
print(data["meta"]) # {'latencyMs': 245, ...}Go
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
body, _ := json.Marshal(map[string]int{"userId": 42})
req, _ := http.NewRequest(
"POST",
"https://soapless.miravy.com/api/v1/ab12cd34ef/my-erp/GetUser",
bytes.NewReader(body),
)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", os.Getenv("SOAPLESS_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Println(result["result"])
}Monitoring & Usage
SOAPless provides built-in tools to monitor your API usage.
Usage Dashboard
Track your monthly API calls, latency trends, and error rates in real time from the dashboard. Reset timing depends on the active plan and billing period, so it is not always the first day of the month.
Rate Limit Headers
Every response includes rate limit headers so you can proactively manage your usage:
X-RateLimit-Limit— Your call limit for the current plan.X-RateLimit-Remaining— Calls remaining in the current period.X-RateLimit-Reset— ISO 8601 timestamp when the current limit window resets.
Account operations
Billing changes, invoices, card updates, and cancellations are handled from the dashboard billing page and Stripe Customer Portal. Permanent account deletion stays available in dashboard settings.
Email is reserved for security reports, privacy requests, legal matters, enterprise inquiries, or account access issues that cannot be resolved from the dashboard.
Next Steps
- Full API Reference — Complete endpoint documentation, response codes, and error types.
- Create an Account — Get started for free with 100 API calls per month.
- View Pricing — Compare plans and find the right fit for your team.