Skip to content

Latest commit

 

History

History
426 lines (321 loc) · 9.88 KB

File metadata and controls

426 lines (321 loc) · 9.88 KB

GET API Reference (SlugSwap)

This document captures the GET API behavior currently used by the SlugSwap project, based on analysis of the public cabalex/get-tools implementation.

Status: unofficial, reverse-engineered usage notes.
Treat this as integration guidance, not vendor-issued API documentation.

Scope

  • Base endpoint and request envelope
  • Session authentication lifecycle
  • Methods used in production-like flows
  • Common request/response patterns
  • Security boundaries for SlugSwap

Source of Truth

Base URL

https://services.get.cbord.com/GETServices/services/json

Requests are sent to:

POST {BASE_URL}/{service}

Examples:

  • POST /authentication
  • POST /user
  • POST /commerce

Request Envelope

All observed methods use a JSON RPC-like body:

{
  "method": "methodName",
  "params": {
    "...": "..."
  }
}

Headers:

  • Content-Type: application/json
  • Accept: application/json

Response Shape

Observed response patterns:

  • Success payload is usually in response
  • Failure payload is usually in exception

Examples:

{
  "response": {
    "accounts": []
  }
}
{
  "exception": {
    "message": "..."
  }
}

Some methods return primitive response values (true, string session id, etc.).

Authentication + Session Lifecycle

0) Obtain a validated GET web session id

Before user.createPIN, the user must complete GET's hosted web login flow.

Observed pattern from get-tools:

  • open the institution GET login URL
  • user authenticates with school credentials
  • GET redirects to a "validated" URL
  • app extracts a UUID-like sessionId from that validated URL

Observed UCSC login URL:

https://get.cbord.com/ucsc/full/login.php?mobileapp=1

Portability note:

  • keep this URL configurable per school; default it to UCSC for now

This validated web sessionId is then passed into user.createPIN.

1) Create a device PIN (user.createPIN)

Used after obtaining a valid GET web session id from the login flow.

Request (observed):

{
  "method": "createPIN",
  "params": {
    "sessionId": "<validated-session-id>",
    "deviceId": "<16-char device id>",
    "PIN": "<4-digit pin>"
  }
}

Result:

  • response === true on success

2) Exchange device PIN for API session (authentication.authenticatePIN)

Request:

{
  "method": "authenticatePIN",
  "params": {
    "pin": "1234",
    "deviceId": "abcdef0123456789",
    "systemCredentials": {
      "userName": "get_mobile",
      "password": "NOTUSED",
      "domain": ""
    }
  }
}

Result:

  • response is a session id string
  • That session id is used in subsequent method calls

3) Keep-alive / validity check (user.updatePIN)

Pattern used by get-tools:

  • call updatePIN with oldPIN == newPIN
  • if it fails, consider credential invalid/revoked

4) Revoke device (user.deletePIN)

Request:

{
  "method": "deletePIN",
  "params": {
    "deviceId": "abcdef0123456789",
    "sessionId": "<session-id>"
  }
}

Result:

  • response === true means revocation succeeded

Commerce Methods

commerce.retrieveAccounts

Purpose:

  • Fetch account balances and tender metadata

Observed request:

{
  "method": "retrieveAccounts",
  "params": {
    "sessionId": "<session-id>"
  }
}

Observed account fields include:

  • id
  • institutionId
  • paymentSystemId
  • userId
  • accountDisplayName
  • accountTender
  • accountType
  • paymentSystemType
  • isActive
  • isAccountTenderActive
  • depositAccepted
  • balance
  • mealEquivValue
  • card-like metadata (lastFour, nameOnMedia, etc.)

Observed top-level payload shape from production-like traffic:

{
  "accounts": [
    {
      "accountDisplayName": "Flexi Dollars",
      "accountType": 3,
      "depositAccepted": true,
      "balance": 50
    },
    {
      "accountDisplayName": "Board",
      "accountType": 1,
      "depositAccepted": false,
      "balance": 0
    }
  ],
  "planName": "STAGING"
}

Observed account labels from UCSC sample payload include:

  • Flexi Dollars
  • Banana Bucks
  • Second Harvest Flexi
  • Slug Points
  • Board
  • Donated Meal
  • Pending Donated Meal
  • Second Harvest Meals

Observed interpretation notes from sample:

  • accountType: 3 appears on stored-value style balances (for example Flexi Dollars, Slug Points).
  • accountType: 1 appears on meal-plan style balances (for example Board, Donated Meal).
  • depositAccepted: true is present on depositable tenders (for example flexi/bucks/points).
  • depositAccepted: false is present on non-deposit meal tenders.
  • isActive and isAccountTenderActive should both be checked before presenting an account as usable.
  • planName is returned at the top level and can help annotate institution-specific plan context.

commerce.retrieveTransactionHistoryWithinDateRange

Purpose:

  • Fetch transaction history for insights and trends

Observed request:

{
  "method": "retrieveTransactionHistoryWithinDateRange",
  "params": {
    "sessionId": "<session-id>",
    "paymentSystemType": 0,
    "queryCriteria": {
      "maxReturnMostRecent": 1000,
      "newestDate": null,
      "oldestDate": "2025-01-01T00:00:00.000Z",
      "accountId": null
    }
  }
}

Observed transaction fields include:

  • transactionId
  • amount
  • resultingBalance
  • postedDate
  • actualDate
  • locationId
  • locationName
  • accountName

authentication.retrievePatronBarcodePayload

Purpose:

  • Fetch payload used to render a scannable barcode (PDF417 in get-tools)

Observed request:

{
  "method": "retrievePatronBarcodePayload",
  "params": {
    "sessionId": "<session-id>"
  }
}

Result:

  • response is barcode payload data consumable by barcode renderer

Observed refresh cadence and TTL notes:

  • get-tools refreshes barcode payload on a 10-second loop in its share flow.
  • Maintainer anecdote suggests the official app refreshes closer to every 5 seconds.
  • Maintainer anecdote also suggests code validity may be around 60 seconds (based on headers).

Implementation guidance for SlugSwap:

  • Start with a 10-second refresh interval for parity with get-tools.
  • If scan failure rates are high, test a 5-second interval.
  • Treat TTL as unknown/unstable until validated against UCSC behavior in production logs.

Method Inventory (Observed)

Service Method Typical Use
authentication authenticatePIN Exchange deviceId + pin for session id
authentication retrievePatronBarcodePayload Generate scan code payload
user createPIN Create device credential
user updatePIN Verify credential still valid
user deletePIN Revoke device credential
commerce retrieveAccounts Read balances/accounts
commerce retrieveTransactionHistoryWithinDateRange Read history and trends

Session Rules to Enforce in SlugSwap

  • Treat deviceId + pin as sensitive credentials.
  • Never expose admin or service tokens in mobile client.
  • Keep raw GET credentials server-side where feasible.
  • Use short-lived, single-purpose claim tokens between app and backend.
  • Separate responsibilities:
    • Client: request claim intent, display result
    • Backend: call GET API, enforce policy, audit actions

Error Handling Guidance

When calling GET API:

  1. If exception is present:
    • classify as auth, permission, or transient failure
    • do not trust partial response
  2. If auth failures repeat:
    • revoke local session and require re-link
  3. For transient network failures:
    • retry with capped exponential backoff
  4. Always log:
    • method name
    • correlation id
    • sanitized error message
    • no secrets in logs

Security Notes for SlugSwap

The get-tools share-code model can grant broad account access. SlugSwap should not replicate that trust model directly.

Recommended production posture:

  • No plaintext credential sharing links.
  • No long-lived client-held GET credentials.
  • Proxy sensitive GET calls through authenticated server routes.
  • Add abuse protection (rate limits, anomaly checks, revocation paths).
  • Keep explicit user consent and revocation UX.

Minimal TypeScript Shapes (Observed)

export type GetEnvelope<TParams> = {
  method: string;
  params: TParams;
};

export type GetResult<TResponse> = {
  response?: TResponse;
  exception?: { message?: string; [k: string]: unknown };
};

export type GetAccount = {
  id: string;
  accountDisplayName: string;
  isActive: boolean;
  isAccountTenderActive: boolean;
  depositAccepted: boolean;
  balance: number | null;
  lastFour?: string | null;
};

export type GetTransaction = {
  transactionId: string;
  amount: number;
  resultingBalance: number;
  postedDate: string;
  actualDate: string;
  locationId: string;
  locationName: string;
};

Open Questions (Track Before Production)

  • Are there documented rate limits or abuse controls from GET?
  • Session expiry duration and invalidation semantics?
  • Which methods are institution-specific vs broadly portable?
  • Failure code taxonomy for robust retries and UX messaging?
  • Any terms-of-service constraints on this integration path?

Change Log

  • 2026-02-09: Initial version created from cabalex/get-tools investigation.
  • 2026-02-10: Added concrete retrieveAccounts payload findings (account labels, field inventory, and observed account-type patterns) from local runtime logs.