21-Apr-2026 — Ramblers Team Emails Mock Server


Revised 23 July 2026. This article now describes the mock after its migration from the original NGX API proposal to the published Ramblers Team Emails 1.0.0 specification. The former Ticket #209 routes, bearer-token authentication and incremental response model are no longer part of the public service.

The Ramblers Team Emails mock server is a live development and test implementation of the API published by Ramblers Head Office. It gives NGX Ramblers and other consumers an isolated, repeatable endpoint for building and testing integrations without using real supporter data.

The service is intentionally more capable than SwaggerHub's generated example responses. Operators can create team-specific datasets, generate varied supporter fixtures, issue scoped API keys, import or export Insight Hub spreadsheets and inspect unsubscribe or bounce writebacks.

Start here

Why the mock still matters

Ramblers Head Office owns the published external interface. The mock does not define a competing API and NGX does not treat it as the source of the specification.

Its purpose is to make the published interface practical to consume:

This keeps the contract, mock and consumers separate while ensuring they implement the same interface.

flowchart LR
    Published["Ramblers Team Emails 1.0.0<br/>SwaggerHub"]
    Contract["Shared contract v1.0.2<br/>types + runtime validation"]

    subgraph testService["Live mock service"]
        API["Express API"]
        Admin["Operator console"]
        Atlas@{ icon: "ngx:mongodb", label: "MongoDB Atlas", pos: "b", h: 48 }
        Admin --> Atlas
        API --> Atlas
    end

    NGX@{ icon: "ngx:ramblers", label: "NGX Ramblers", pos: "b", h: 48 }
    Other["Other API consumers"]

    Published --> Contract
    Contract --> API
    Contract --> NGX
    NGX --> API
    Other --> API

    style testService fill:#E8F5EE,stroke:#9BC8AB,stroke-width:2px,rx:12,ry:12,color:#404143

The current API

The mock exposes the three operations in Ramblers Team Emails 1.0.0:

Method Path Purpose
GET /get_supporters Return the current supporter snapshot for a team
POST /unsubscribe Record an unsubscribe request for a supporter
POST /bounced_email Record a hard or soft email bounce

Every operation uses the published query credentials:

The key and team must match. A key issued for one team cannot read supporters or submit writebacks for another.

The retired routes from the original proposal deliberately return 404:

There is no compatibility façade for those routes. A consumer using the old interface should fail clearly rather than appear to work against an obsolete contract.

Supporter snapshots

GET /get_supporters returns a complete snapshot rather than an incremental delta. The published response covers:

The mock generates representative combinations of these states. This matters particularly for non-members, because membershipNo can be null while memberRef and contactId remain available.

Consumers must not infer a deletion, resignation or transfer merely because a supporter is missing from a later snapshot. The published API does not currently define the meaning of disappearance, so NGX retains the previous record for review.

Unsubscribe and bounce writebacks

The two write operations use memberRef and email address rather than the former membership-number path.

POST /bounced_email accepts the published Hard and Soft values. The mock records the team, supporter, bounce type, received time and outcome so duplicate or repeated provider events can be inspected.

POST /unsubscribe is also recorded, but the mock deliberately does not invent the resulting consent change. Ramblers Head Office still needs to confirm:

Until those semantics are confirmed, an accepted mock unsubscribe means that the request was structurally valid and auditable, not that a locally invented consent rule has been applied.

Shared contract and drift detection

The mock and NGX consume @ramblers/sf-contract v1.0.2.

The package contains:

The contract repository checks the live resolved SwaggerHub definition against its pinned copy. A material upstream change produces a reviewable failure rather than silently changing consumer behaviour. Formatting-only differences are normalised away.

flowchart LR
    Swagger["SwaggerHub<br/>resolved OpenAPI"]
    Pinned["Pinned upstream definition"]
    Schemas["Types + Zod schemas"]
    Mock["Mock build and tests"]
    NGX["NGX build and tests"]

    Swagger --> Drift{"Semantic drift check"}
    Pinned --> Drift
    Drift --> Schemas
    Schemas --> Mock
    Schemas --> NGX

Operator and team isolation

The operator console is separate from public API authentication.

An operator signs in, creates or selects a team and can then:

API keys are shown once and stored only as hashes plus non-secret prefixes. Every supporter, key and writeback record carries the owning team code, and all data access is filtered by it.

The root operator can administer the service. Ordinary operators only see teams they own.

Typical test flow

  1. Sign in to the operator console.
  2. Create or select a team using the intended team_code.
  3. Import Insight Hub data or generate synthetic supporters.
  4. Generate an API key for that team and copy it when shown.
  5. Open the Swagger UI.
  6. Call GET /get_supporters with the key and matching team code.
  7. Exercise hard and soft bounce calls or an unsubscribe request.
  8. Return to the operator console and inspect the writeback history.
  9. Try the same key with a different team code to confirm isolation.

Infrastructure and deployment

The service remains deliberately small:

Pushes to main run typechecking, linting, build and tests before deployment. The latest implementation includes route tests for valid and invalid credentials, cross-team attempts, published response shapes, hard and soft bounce values and rejection of the retired routes.

Insight Hub during transition

Insight Hub import and export remain useful test facilities because groups still depend on spreadsheets for supporter fields not included in API 1.0.0.

That compatibility should not be mistaken for the desired end state. The missing supporter-field set and the operational and GDPR implications of continuing to handle exports are tracked in NGX Ticket #334.

Known Phase One questions

The mock follows the published document without answering questions that belong to Ramblers Head Office:

These are visible constraints rather than hidden assumptions.

Current implementation tickets

References

Questions or suggested test scenarios can be raised through the mock repository or sent through NGX support.