• SPECML
    • A-SPECML

    A-SPECML

    ASPECML - API Specification with SPECML#

    What is ASPECML?#

    ASPECML extends SPECML for describing REST APIs. Define your endpoints, request structures, responses, and error cases in one place using familiar SPECML syntax.
    Single source of truth for:
    API endpoints and routes
    Request validation
    Response structures
    Error scenarios
    Authentication requirements
    API documentation
    From ASPECML specs, generate:
    API documentation (OpenAPI/Swagger)
    Client libraries (JavaScript, Python, etc.)
    Server-side validators
    Mock servers
    Integration tests
    Contract tests

    Why ASPECML?#

    The Problem:
    Your team maintains:
    API docs in Swagger/OpenAPI
    Request validators in code
    Response types in TypeScript
    Integration tests
    Client SDK definitions
    When the API changes, you update all of these separately. They drift. Bugs happen.
    The Solution:
    Define your API once in ASPECML. Generate everything else.
    CreateUserEndpoint {
      method POST
      path /api/users
      
      body {
        email string<isEmail>
        password string<minLength:8>
        username string<minLength:3>
      }
      
      response {
        success {
          status 201
          body {
            id string<ulid>
            email string
            username string
            createdAt string<isISO>
          }
        }
        
        validation_error {
          status 422
          body {
            error string
            details[] {
              field string
              message string
            }
          }
        }
      }
    }

    ASPECML vs SPECML#

    ASPECML uses SPECML syntax but interprets certain fields with API-specific meaning:
    FieldSPECML InterpretationASPECML Interpretation
    methodField named "method"HTTP method (GET, POST, etc.)
    pathField named "path"API route
    bodyNested objectRequest/response body
    headersNested objectHTTP headers
    queryNested objectQuery parameters
    paramsNested objectPath parameters
    responseNested objectAPI response scenarios
    statusField named "status"HTTP status code
    Everything else follows standard SPECML syntax - references, copy operators, arrays, modifiers, enums, etc.

    Basic Endpoint Structure#

    Every ASPECML endpoint follows this pattern:
    EndpointName {
      method [HTTP_METHOD]
      path [URL_PATH]
      
      headers { }      // Optional
      query { }        // Optional
      params { }       // Optional
      body { }         // Optional
      
      response {
        scenario_name {
          status [CODE]
          headers { }  // Optional
          body { }     // Optional
        }
      }
    }
    Required fields:
    method - HTTP method
    path - API route
    response - At least one response scenario
    Optional fields:
    headers - Request headers
    query - Query string parameters
    params - Path parameters
    body - Request body

    HTTP Methods#

    Specify the HTTP method for your endpoint:
    GetUserEndpoint {
      method GET
      path /api/users/:id
    }
    
    CreateUserEndpoint {
      method POST
      path /api/users
    }
    
    UpdateUserEndpoint {
      method PUT
      path /api/users/:id
    }
    
    PatchUserEndpoint {
      method PATCH
      path /api/users/:id
    }
    
    DeleteUserEndpoint {
      method DELETE
      path /api/users/:id
    }
    Supported methods: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS

    URL Paths#

    Define your API routes:
    // Simple paths
    ListUsersEndpoint {
      method GET
      path /api/users
    }
    
    // With path parameters (use :paramName)
    GetUserEndpoint {
      method GET
      path /api/users/:id
    }
    
    // Nested resources
    GetOrderItemEndpoint {
      method GET
      path /api/orders/:orderId/items/:itemId
    }
    
    // Versioned APIs
    CreateUserV2Endpoint {
      method POST
      path /api/v2/users
    }
    Path parameter syntax: Use :paramName for dynamic segments.

    Path Parameters#

    Define and validate path parameters:
    GetUserEndpoint {
      method GET
      path /api/users/:userId
      
      params {
        userId string<ulid>
      }
    }
    
    GetOrderItemEndpoint {
      method GET
      path /api/orders/:orderId/items/:itemId
      
      params {
        orderId string<ulid>
        itemId string<ulid>
      }
    }
    All path parameters should be defined in the params block with their validation rules.

    Query Parameters#

    Define URL query string parameters:
    ListUsersEndpoint {
      method GET
      path /api/users
      
      query {
        page? number<min:1>
        limit? number<min:1|max:100>
        status? string(active|inactive|suspended)
        search? string
        sortBy? string(name|email|createdAt)
        sortOrder? string(asc|desc)
      }
    }
    Usage: /api/users?page=2&limit=50&status=active&sortBy=name&sortOrder=desc
    Optional by default: Most query parameters are optional. Use required validation if needed.

    Request Headers#

    Define required or optional request headers:
    GetUserEndpoint {
      method GET
      path /api/users/:id
      
      headers {
        Authorization string
        X-Request-ID? string<ulid>
        Accept? string(application/json|application/xml)
      }
      
      params {
        id string<ulid>
      }
    }
    Common headers:
    Authorization - Auth tokens
    Content-Type - Request body format
    Accept - Response format preference
    X-Request-ID - Request tracing
    X-API-Key - API authentication

    Request Body#

    Define the structure of request payloads:
    CreateUserEndpoint {
      method POST
      path /api/users
      
      headers {
        Content-Type string(application/json)
      }
      
      body {
        email string<isEmail|lowercase>
        password string<minLength:8|maxLength:100>
        username string<minLength:3|maxLength:20>
        firstName string<trim>
        lastName string<trim>
        age? number<min:13|max:120>
      }
    }
    Nested bodies:
    CreateOrderEndpoint {
      method POST
      path /api/orders
      
      body {
        customerId string<ulid>
        items[] {
          productId string<ulid>
          quantity number<min:1>
          unitPrice number<min:0>
        }
        shippingAddress {
          street string
          city string
          zipCode string
          country string<length:2|uppercase>
        }
        notes? string
      }
    }

    Response Structure#

    Responses contain one or more scenarios (success, error cases):
    CreateUserEndpoint {
      method POST
      path /api/users
      
      body {
        email string<isEmail>
        password string<minLength:8>
      }
      
      response {
        success {
          status 201
          body {
            id string<ulid>
            email string
            createdAt string<isISO>
          }
        }
        
        validation_error {
          status 422
          body {
            error string
            message string
          }
        }
        
        server_error {
          status 500
          body {
            error string
            message string
          }
        }
      }
    }
    Response scenario names are arbitrary - use descriptive names like success, not_found, unauthorized, etc.

    Response Status Codes#

    Define HTTP status codes for each scenario:
    GetUserEndpoint {
      method GET
      path /api/users/:id
      
      response {
        success {
          status 200
          body {
            id string
            email string
            name string
          }
        }
        
        not_found {
          status 404
          body {
            error string
            message string
          }
        }
        
        unauthorized {
          status 401
          body {
            error string
            message string
          }
        }
      }
    }
    Common status codes:
    200 - OK (successful GET, PUT, PATCH)
    201 - Created (successful POST)
    204 - No Content (successful DELETE)
    400 - Bad Request
    401 - Unauthorized
    403 - Forbidden
    404 - Not Found
    422 - Unprocessable Entity (validation error)
    500 - Internal Server Error

    Response Headers#

    Define response headers:
    CreateUserEndpoint {
      method POST
      path /api/users
      
      response {
        success {
          status 201
          headers {
            Location string
            X-Request-ID string
            X-RateLimit-Remaining number
          }
          body {
            id string
            email string
          }
        }
      }
    }

    Multiple Success Scenarios#

    APIs can have multiple successful outcomes:
    UpdateUserEndpoint {
      method PUT
      path /api/users/:id
      
      body {
        email? string<isEmail>
        name? string
      }
      
      response {
        success_updated {
          status 200
          body {
            id string
            email string
            name string
            updatedAt string<isISO>
          }
        }
        
        success_no_changes {
          status 304
          body {
            message string
          }
        }
        
        not_found {
          status 404
          body {
            error string
          }
        }
      }
    }

    Complete Basic Example#

    // Create a new user account
    CreateUserEndpoint {
      method POST
      path /api/users
      
      headers {
        Content-Type string(application/json)
        X-Request-ID? string<ulid>
      }
      
      body {
        email string<isEmail|lowercase|trim>
        password string<minLength:8|maxLength:100>
        username string<minLength:3|maxLength:20|trim>
        firstName string<trim>
        lastName string<trim>
      }
      
      response {
        success {
          status 201
          headers {
            Location string
          }
          body {
            id string<ulid>
            email string
            username string
            firstName string
            lastName string
            createdAt string<isISO>
          }
        }
        
        validation_error {
          status 422
          body {
            error string
            message string
            details[] {
              field string
              message string
            }
          }
        }
        
        conflict {
          status 409
          body {
            error string
            message string
            conflictingField string
          }
        }
      }
    }
    
    // Retrieve user by ID
    GetUserEndpoint {
      method GET
      path /api/users/:userId
      
      headers {
        Authorization string
      }
      
      params {
        userId string<ulid>
      }
      
      response {
        success {
          status 200
          body {
            id string
            email string
            username string
            firstName string
            lastName string
            createdAt string<isISO>
            updatedAt string<isISO>
          }
        }
        
        not_found {
          status 404
          body {
            error string
            message string
          }
        }
        
        unauthorized {
          status 401
          body {
            error string
            message string
          }
        }
      }
    }
    
    // List users with filtering
    ListUsersEndpoint {
      method GET
      path /api/users
      
      headers {
        Authorization string
      }
      
      query {
        page? number<min:1>
        limit? number<min:1|max:100>
        status? string(active|inactive|suspended)
        search? string
      }
      
      response {
        success {
          status 200
          body {
            users[] {
              id string
              email string
              username string
              status string
            }
            pagination {
              page number
              limit number
              total number
              hasMore boolean
            }
          }
        }
        
        unauthorized {
          status 401
          body {
            error string
            message string
          }
        }
      }
    }

    Key Takeaways#

    1.
    ASPECML uses SPECML syntax - Everything you learned applies here
    2.
    Specific fields have API meaning - method, path, headers, query, params, body, response, status
    3.
    Multiple response scenarios - Define success and all error cases
    4.
    Path parameters use :name - Dynamic URL segments
    5.
    Query parameters are typically optional - Use ? marker
    6.
    Request and response bodies - Use full SPECML features (references, arrays, modifiers, enums)
    7.
    Status codes are numbers - 200, 201, 404, 422, 500, etc.
    Next sections will cover:
    Reusing definitions (references and copy operator)
    Common patterns for APIs
    Authentication and authorization
    Pagination
    File uploads
    Webhooks
    Real-world fintech API examples
    Modified at 2025-10-08 08:20:53
    Previous
    SPECML
    Built with