Developers · Getting started

Your first Andromeda API call in ten minutes.

Get credentials, swap them for a token, make your first read, make your first write, learn the error shape. That's the whole story — the rest is just more endpoints.

Standard OAuth2. Standard REST. Standard RFC 7807 errors. No bespoke SDK required.

How the platform is organised.

Andromeda splits reads and writes across two APIs — a Queries API for GET requests, and a Commands API for POST, PUT and DELETE. A third service, the Identity server, issues OAuth2 tokens. All three are accessible on both a test and a production environment.

ServiceTestProduction
Identity (OAuth2) test-portal-identity.azurewebsites.net portal-identity.azurewebsites.net
Queries API (reads) test-portal-queries-api.azurewebsites.net portal-queries-api.azurewebsites.net
Commands API (writes) test-portal-api.azurewebsites.net portal-api.azurewebsites.net

Every integration starts against test. Promotion to production is a config change, not a code change.

Tell us you're building, get a client.

  1. Talk to us

    Email info@androtech.com or book a call. Tell us the use case — reporting, menu automation, loyalty sync, etc. — and we'll issue a non-production organisation with test data.

  2. Receive a client_id and client_secret

    You get a pair of credentials scoped to your organisation, plus a handful of test locations seeded with products, prices and a stream of synthetic orders so you have something realistic to read and write against.

  3. Keep the secret in a secret store

    Azure Key Vault, AWS Secrets Manager, 1Password — anything but source control. The secret never needs to appear in browser code; OAuth2 client_credentials is a server-to-server flow.

One POST. One JWT. Good for an hour.

Request an access token

Standard OAuth2 client_credentials grant. The response is a short-lived JWT signed with our platform certificate — attach it as a Bearer header on every subsequent call.

POST
Request
POST https://test-portal-identity.azurewebsites.net/connect/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=<your_client_id>
&client_secret=<your_client_secret>
&scope=andromeda-api
Response — 200 OK
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6...",
  "expires_in": 3600,
  "token_type": "Bearer",
  "scope": "andromeda-api"
}
Use it on every call
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6...

// Cache the token for its lifetime. Refresh a few minutes
// before it expires — don't request one per API call.

List the locations you have access to.

GET /organizations/{organizationId}/locations

Every endpoint is scoped to an organisation. Your organizationId is baked into the token claims — you can only touch your own data. A locations call is the canonical "am I wired up correctly?" first request.

GET
Request
GET /organizations/{organizationId}/locations
Authorization: Bearer <access_token>
Response — 200 OK
[
  {
    "id": "7f2b6c9e-1a4d-4f12-9b23-5c8e0d1a3b42",
    "name": "Camden High Street",
    "addressLine1": "214 Camden High Street",
    "city": "London",
    "postcode": "NW1 8QR",
    "active": true
  },
  {
    "id": "a31f8102-e74a-4d66-9c3a-b0fdd7e29471",
    "name": "Shoreditch",
    "addressLine1": "88 Great Eastern Street",
    "city": "London",
    "postcode": "EC2A 3JB",
    "active": true
  }
]
Keep the location IDs
// Most read endpoints take an optional ?LocationId= filter.
// Keep these GUIDs — you'll use them everywhere.

Change a price. Watch it propagate.

PUT /organizations/{organizationId}/products/{productId}/pricing

Write endpoints live on the Commands API. The host changes (from *-queries-api to *-portal-api) but the bearer token and the org/location scoping are identical. A 202 means accepted and queued for propagation.

PUT
Request
PUT /organizations/{organizationId}/products/{productId}/pricing
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "variants": [
    {
      "name": "Regular",
      "prices": [
        { "occasion": "Delivery",   "price": 9.50, "taxRate": 0.20 },
        { "occasion": "Collection", "price": 8.50, "taxRate": 0.20 }
      ]
    }
  ]
}
Response — 202 Accepted
// Within seconds the new price is live on the website,
// the kiosk, the POS and every aggregator you sync to.

Every error is RFC 7807. Every error carries a trace ID.

Validation failure — 400 Bad Request

If a required field is missing, mutually-exclusive filters are supplied together, or a date range is invalid, you get a ProblemDetails body describing what's wrong and a traceId you can quote to our helpdesk.

PROBLEM
Response — 400 Bad Request
{
  "type": "https://portal-queries-api.azurewebsites.net/errors/bad-request",
  "title": "Bad Request",
  "status": 400,
  "detail": "PeriodMonths is required when CustomerMarketingSelection is 'All'.",
  "traceId": "0HN1GJK8Q2V4L:00000001"
}
Common statuses
401 // missing / expired token — refresh and retry
403 // token valid but org or location not in scope
404 // resource not found, or location not in this organisation
409 // concurrent write — refetch and retry
500 // server error — quote the traceId to support@androtech.com

Where to go next.

You now have a working token, you can read, you can write, you understand the error shape. Every remaining problem is "which endpoints do I need?" — pick the area that matches what you're building.

Ready for credentials?

Email us with what you're building and we'll send a test client, seeded data, and a technical contact inside one working day.

Request test access