Skip to content

CFA Lookup API

The CFA Lookup API lets approved partner systems confirm a Clearing and Forwarding Agent by exact identifier within a specified association.

Both versions support one exact lookup at a time. They do not return association-wide member lists. V1 remains backward compatible; V2 adds separately authorized contact, membership lifecycle, restriction context, current disciplinary standing, and association-account financial standing.

Environments

Environment Base URL Token issuer
AWS preproduction https://api.preprod.taffa.cfhub.net/core https://keycloak.preprod.taffa.cfhub.net/realms/cfhub
VPS https://api.taffa.cfhub.net/core https://keycloak.taffa.cfhub.net/realms/cfhub
Production https://api.clearingagent.co.tz/core https://auth.clearingagent.co.tz/realms/cfhub

TAFFA will confirm the active base URL, token issuer, client_id, and client_secret during onboarding.

Authentication

Partners authenticate with a confidential Keycloak client using the OAuth2 client_credentials grant.

  • V1 requires PARTNER_CFA_LOOKUP.
  • V2 requires both PARTNER_CFA_LOOKUP and PARTNER_CFA_CONTACT_READ. TAFFA grants the contact role only after approving the integration's purpose and data handling.
  • V2 includes the optional disciplinary object only when the token also has PARTNER_CFA_DISCIPLINARY_READ. A token without this role may still call V2, but the field is omitted rather than returned as null.
  • V2 includes the optional financialStanding object only when the token also has PARTNER_CFA_FINANCIAL_READ. It is omitted without that role. This role does not grant invoice, amount, payment-reference, or bank-detail access.
curl -X POST "$ISSUER_URL/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=$CLIENT_ID" \
  -d "client_secret=$CLIENT_SECRET"

Use the returned access_token as a bearer token. Cache the token until it is close to expiry. Do not send the client secret to the lookup endpoint.

Lookup Request

POST /api/v1/cfa/lookup or POST /api/v2/cfa/lookup

{
  "associationCode": "TAFFA",
  "lookupType": "TIN",
  "identifier": "104006787"
}
Field Required Description
associationCode Yes Association code. TAFFA and TACAS are supported when their registry data is available.
lookupType Yes One of TIN, ASSOCIATION_MEMBERSHIP_NUMBER, LICENSE_NUMBER, CERTIFICATE_ID, REGISTRATION_NUMBER.
identifier Yes Exact identifier value. TIN is normalized to digits only. Other values are matched case-insensitively after trimming.

Example:

curl -X POST "$BASE_URL/api/v1/cfa/lookup" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Request-ID: partner-generated-id" \
  -d '{"associationCode":"TAFFA","lookupType":"TIN","identifier":"104006787"}'

Membership-number lookup:

{
  "associationCode": "TAFFA",
  "lookupType": "ASSOCIATION_MEMBERSHIP_NUMBER",
  "identifier": "TAFFA-0001"
}

Interactive API Reference

Scalar provides the OpenAPI schema, request examples, bearer-token authorization, and an interactive client:

  • AWS preproduction: https://api.preprod.taffa.cfhub.net/core/api-docs/cfa
  • VPS: https://api.taffa.cfhub.net/core/api-docs/cfa
  • Production: https://api.clearingagent.co.tz/core/api-docs/cfa

The machine-readable partner specification is at /v3/api-docs/cfa-partner under the same base URL.

Successful Response

V1 returns regulatory status and identifiers only. It does not expose company email, phone, address, owners, users, or internal profile fields.

{
  "success": true,
  "message": "CFA lookup completed",
  "data": {
    "lookup": {
      "requestedType": "TIN",
      "requestedValue": "104006787",
      "matchedType": "TIN",
      "matchedValue": "104006787"
    },
    "cfa": {
      "companyName": "Example Clearing Agent Ltd",
      "tin": "104006787",
      "registrationNumber": "REG-001",
      "businessRegistrationNumber": "BRELA-001",
      "active": true,
      "memberStatus": "ACTIVE",
      "approvalStatus": "APPROVED",
      "association": {
        "code": "TAFFA",
        "name": "TAFFA",
        "membershipNumber": "TAFFA-0001",
        "membershipType": "ordinary"
      },
      "license": {
        "number": "LIC-001",
        "status": "ACTIVE",
        "expiresAt": "2026-12-31T23:59:59"
      },
      "consignmentRegistrationRestricted": false
    }
  },
  "errorCode": null,
  "timestamp": "2026-07-02T12:00:00"
}

V2 response

V2 adds the stable company identifier, approved primary company contact, membership validity dates, restriction explanation, and—when separately authorized—current disciplinary and association-account financial standing. It still does not expose addresses, owners, users, internal evidence, private notes, invoice details, amounts, bank details, or association-wide records.

{
  "success": true,
  "message": "CFA lookup completed",
  "data": {
    "lookup": {
      "requestedType": "TIN",
      "requestedValue": "999900001",
      "matchedType": "TIN",
      "matchedValue": "999900001"
    },
    "cfa": {
      "companyId": "00000000-0000-4000-8000-000000000001",
      "companyName": "TCAMS Synthetic CFA Demo Ltd",
      "tin": "999900001",
      "registrationNumber": "DEMO-REG-0001",
      "businessRegistrationNumber": "DEMO-BRELA-0001",
      "active": true,
      "memberStatus": "ACTIVE",
      "approvalStatus": "APPROVED",
      "contact": {
        "email": "cfa-demo@example.invalid",
        "phone": "+255700000001"
      },
      "association": {
        "code": "TAFFA",
        "name": "TAFFA",
        "membershipNumber": "TAFFA-DEMO-0001",
        "membershipType": "ordinary",
        "membershipValidFrom": "2026-01-01",
        "membershipValidTo": "2026-12-31"
      },
      "license": {
        "number": "DEMO-LIC-0001",
        "status": "ACTIVE",
        "expiresAt": "2026-12-31T23:59:59"
      },
      "consignmentRegistrationRestricted": false,
      "consignmentRestrictionReason": null,
      "consignmentRestrictionSetAt": null,
      "consignmentRestrictionSource": null,
      "disciplinary": {
        "flagged": false,
        "disciplinaryStatus": "CLEAN",
        "reason": null,
        "reference": null,
        "effectiveFrom": null,
        "effectiveTo": null,
        "activeActionCount": 0
      },
      "financialStanding": {
        "status": "CLEAR",
        "accountInGoodStanding": true,
        "outstandingInvoiceCount": 0,
        "overdueInvoiceCount": 0,
        "oldestOutstandingDueAt": null,
        "lastSettledAt": "2026-06-26T10:30:00",
        "asOf": "2026-07-16T12:00:00"
      }
    }
  },
  "errorCode": null,
  "timestamp": "2026-07-16T12:00:00"
}

The 999900001, TAFFA-DEMO-0001, and DEMO-LIC-0001 identifiers are reserved synthetic fixtures in preproduction only. They must never be inserted into production.

V2 responses send Cache-Control: no-store and Pragma: no-cache. The default rate limit is 60 requests per minute per OAuth client; use X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, and Retry-After response headers for client-side backoff.

Current Disciplinary Standing

The disciplinary object is a derived current standing, not a complete disciplinary history. It is present only for clients granted PARTNER_CFA_DISCIPLINARY_READ.

An action contributes to the current standing only when all of the following are true:

  • its lifecycle is ACTIVE or UNDER_APPEAL;
  • it is marked for external lookup visibility;
  • its effective time has started and its expiry time has not passed;
  • it has not been resolved; and
  • enforcement has not been stayed during an appeal.

Resolved, cancelled, expired, future, draft, hidden, and stayed actions remain in the association's audit history but do not flag the company. If several actions are current, the API returns the highest-priority standing in this order: REVOKED, SUSPENDED, FINE, WARNING. activeActionCount reports the number of current enforceable actions.

Field Values / meaning
flagged true only when one or more current enforceable actions exist.
disciplinaryStatus CLEAN, WARNING, FINE, SUSPENDED, or REVOKED.
reason Association-approved public reason for the highest-priority current action; never internal case notes or evidence.
reference Public disciplinary reference for the highest-priority current action.
effectiveFrom, effectiveTo Effective window for the returned action. effectiveTo may be null.
activeActionCount Total current enforceable actions.

Example flagged response fragment:

{
  "disciplinary": {
    "flagged": true,
    "disciplinaryStatus": "SUSPENDED",
    "reason": "Membership suspended pending resolution of an active compliance finding",
    "reference": "DISC-2026-A1B2C3D4",
    "effectiveFrom": "2026-07-16T09:00:00",
    "effectiveTo": null,
    "activeActionCount": 1
  }
}

When the action is resolved, a subsequent lookup returns flagged: false and disciplinaryStatus: CLEAN; the historical action is not exposed through the partner lookup.

Association Financial Standing

The optional financialStanding object answers a narrow question: is the CFA's account with the association currently clear? It is present only for clients granted PARTNER_CFA_FINANCIAL_READ.

This is association billing standing, not a statement about the CFA's commercial solvency or the financial health of its customer business. The calculation includes only association-owned charges such as membership, fines, training, and LMS fees. Invoices issued by the CFA to its own customers are explicitly excluded, even if their wording resembles an association charge.

Field Values / meaning
status CLEAR when no association invoice is outstanding; PAYMENT_DUE when payment is outstanding but not overdue; OVERDUE when at least one association invoice is past due; UNKNOWN when the source ledger cannot be read reliably.
accountInGoodStanding true only for CLEAR, false for PAYMENT_DUE or OVERDUE, and null for UNKNOWN.
outstandingInvoiceCount Count of association-owned invoices awaiting full settlement; null for UNKNOWN.
overdueInvoiceCount Count of those outstanding invoices that are explicitly overdue or past their due date; null for UNKNOWN.
oldestOutstandingDueAt Earliest due date among current outstanding association invoices, when available.
lastSettledAt Most recent settlement time for an association-owned invoice, when available.
asOf Time at which TCAMS derived the standing.

Example overdue response fragment:

{
  "financialStanding": {
    "status": "OVERDUE",
    "accountInGoodStanding": false,
    "outstandingInvoiceCount": 2,
    "overdueInvoiceCount": 1,
    "oldestOutstandingDueAt": "2026-07-01T00:00:00",
    "lastSettledAt": "2026-06-20T10:30:00",
    "asOf": "2026-07-16T12:00:00"
  }
}

The object never contains invoice numbers, categories, line items, amounts, balances, currencies, payment references, settlement-account details, or bank data. A CLEAR standing means only that TCAMS found no current outstanding association-owned invoice; it does not erase historical invoices.

Errors

HTTP status errorCode Meaning
400 INVALID_LOOKUP_REQUEST Required field is missing or lookupType is not supported.
401 UNAUTHORIZED Token is missing, expired, or invalid.
403 FORBIDDEN Token is valid but lacks a role required by the selected API version.
404 CFA_NOT_FOUND No CFA matched the association and identifier.
429 CFA_LOOKUP_RATE_LIMITED The V2 per-client rate limit was exceeded. Retry after the number of seconds in Retry-After.
500 CFA_LOOKUP_FAILED TAFFA could not complete the lookup.

Example not found response:

{
  "success": false,
  "message": "No CFA matched the supplied association and identifier.",
  "data": null,
  "errorCode": "CFA_NOT_FOUND",
  "timestamp": "2026-07-02T12:00:00"
}

Audit And Support

TAFFA logs every lookup for operational audit. The audit record includes request id, partner client id, token subject, source IP, forwarded IP headers, user agent, association code, lookup type, normalized identifier hash, outcome, HTTP status, matched company id where available, response source, error code, timestamps, elapsed time, redacted request JSON, and a sanitized response. V2 email, phone, public disciplinary reason, and the complete financial-standing object are never persisted in lookup audit JSON.

Partners should send X-Request-ID on every call and include that value when asking TAFFA support to investigate a lookup.

Credential handling:

  • Store client_secret only in a secure secret manager.
  • Rotate credentials when requested by TAFFA or after suspected exposure.
  • Never log bearer tokens or client secrets in partner systems.
  • Do not share credentials across environments.