Files
as4-411/docs/api/openapi.yaml
defiQUG c24ae925cf
Some checks failed
CI / lint (push) Has been cancelled
CI / build (push) Has been cancelled
Initial commit: AS4/411 directory and discovery service for Sankofa Marketplace
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 08:44:20 -08:00

531 lines
17 KiB
YAML

openapi: 3.0.3
info:
title: as4-411 Directory and Resolver API
description: |
Standards-aware directory and discovery service for AS4, SS7, and messaging gateways.
See [data-model](../architecture/data-model.md) and [resolution-algorithm](../architecture/resolution-algorithm.md).
version: 0.1.0
servers:
- url: /api
description: API base path
tags:
- name: Resolver
description: Gateway-facing resolution
- name: Admin
description: Directory management
- name: System
description: Health and metrics
paths:
# --- Resolver API (gateway-facing) ---
/v1/resolve:
post:
tags: [Resolver]
summary: Resolve identifiers to routing directives
description: |
For ISO 20022 FI-to-FI, use service = `iso20022.fi` and action = `credit.transfer`, `fi.credit.transfer`, `payment.status`, `payment.cancellation`, `resolution.of.investigation`, `statement`, or `notification`.
Profile returned: `as4.fifi.iso20022.v1`.
operationId: resolve
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/ResolveRequest" }
example:
identifiers:
- type: as4.partyId
value: BANKUS33XXX
scope: BIC
serviceContext:
service: iso20022.fi
action: credit.transfer
responses:
"200":
description: Resolution result
content:
application/json:
schema: { $ref: "#/components/schemas/ResolveResponse" }
example:
primary:
target_protocol: as4
target_address: https://as4.bankus.com/fi
transport_profile: as4.fifi.iso20022.v1
security:
signRequired: true
encryptRequired: true
keyRefs: [vault://certs/bankus/iso20022]
service_context:
service: iso20022.fi
action: credit.transfer
resolution_trace:
- source: internal directory
"400":
description: Invalid request
"503":
description: Resolver unavailable
/v1/bulk-resolve:
post:
tags: [Resolver]
summary: Batch resolve multiple requests
operationId: bulkResolve
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [requests]
properties:
requests:
type: array
items: { $ref: "#/components/schemas/ResolveRequest" }
responses:
"200":
description: Batch resolution results
content:
application/json:
schema:
type: object
properties:
results:
type: array
items: { $ref: "#/components/schemas/ResolveResponse" }
traceId: { type: string, format: uuid }
# --- System ---
/v1/health:
get:
tags: [System]
summary: Health check
operationId: health
responses:
"200":
description: Service healthy
content:
application/json:
schema:
type: object
properties:
status: { type: string, enum: [ok, degraded] }
version: { type: string }
checks: { type: object }
/v1/metrics:
get:
tags: [System]
summary: Prometheus metrics
operationId: metrics
responses:
"200":
description: Prometheus text format
content:
text/plain: {}
# --- Admin API (CRUD) ---
/v1/admin/tenants:
get:
tags: [Admin]
summary: List tenants
operationId: listTenants
responses:
"200": { description: List of tenants }
post:
tags: [Admin]
summary: Create tenant
operationId: createTenant
requestBody:
{ content: { "application/json": { schema: { $ref: "#/components/schemas/Tenant" } } } }
responses:
"201": { description: Created }
"400": { description: Validation error }
/v1/admin/tenants/{tenantId}:
get:
tags: [Admin]
summary: Get tenant
operationId: getTenant
parameters: [{ name: tenantId, in: path, required: true, schema: { type: string } }]
responses:
"200": { description: Tenant }
"404": { description: Not found }
put:
tags: [Admin]
summary: Update tenant
operationId: updateTenant
parameters: [{ name: tenantId, in: path, required: true, schema: { type: string } }]
requestBody:
{ content: { "application/json": { schema: { $ref: "#/components/schemas/Tenant" } } } }
responses:
"200": { description: Updated }
"404": { description: Not found }
delete:
tags: [Admin]
summary: Delete tenant
operationId: deleteTenant
parameters: [{ name: tenantId, in: path, required: true, schema: { type: string } }]
responses:
"204": { description: Deleted }
"404": { description: Not found }
/v1/admin/participants:
get:
tags: [Admin]
summary: List participants
parameters:
- name: tenantId
in: query
schema: { type: string }
responses:
"200": { description: List of participants }
post:
tags: [Admin]
summary: Create participant
operationId: createParticipant
requestBody:
{
content: { "application/json": { schema: { $ref: "#/components/schemas/Participant" } } },
}
responses:
"201": { description: Created }
"400": { description: Validation error }
/v1/admin/participants/{participantId}:
get:
tags: [Admin]
summary: Get participant
operationId: getParticipant
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
responses:
"200": { description: Participant }
"404": { description: Not found }
put:
tags: [Admin]
summary: Update participant
operationId: updateParticipant
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
requestBody:
{
content: { "application/json": { schema: { $ref: "#/components/schemas/Participant" } } },
}
responses:
"200": { description: Updated }
"404": { description: Not found }
delete:
tags: [Admin]
summary: Delete participant
operationId: deleteParticipant
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
responses:
"204": { description: Deleted }
"404": { description: Not found }
/v1/admin/participants/{participantId}/identifiers:
get:
tags: [Admin]
summary: List identifiers for participant
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
responses:
"200": { description: List of identifiers }
post:
tags: [Admin]
summary: Add identifier
operationId: createIdentifier
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
requestBody:
{ content: { "application/json": { schema: { $ref: "#/components/schemas/Identifier" } } } }
responses:
"201": { description: Created }
"400": { description: Validation error }
/v1/admin/participants/{participantId}/endpoints:
get:
tags: [Admin]
summary: List endpoints for participant
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
responses:
"200": { description: List of endpoints }
post:
tags: [Admin]
summary: Add endpoint
operationId: createEndpoint
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
requestBody:
{ content: { "application/json": { schema: { $ref: "#/components/schemas/Endpoint" } } } }
responses:
"201": { description: Created }
"400": { description: Validation error }
/v1/admin/participants/{participantId}/credentials:
get:
tags: [Admin]
summary: List credential refs for participant
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
responses:
"200": { description: List of credential refs }
post:
tags: [Admin]
summary: Add credential reference
operationId: createCredential
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
requestBody:
{
content:
{ "application/json": { schema: { $ref: "#/components/schemas/CredentialRef" } } },
}
responses:
"201": { description: Created }
"400": { description: Validation error }
/v1/admin/policies:
get:
tags: [Admin]
summary: List policies
parameters:
- name: tenantId
in: query
schema: { type: string }
responses:
"200": { description: List of policies }
post:
tags: [Admin]
summary: Create policy
operationId: createPolicy
requestBody:
{ content: { "application/json": { schema: { $ref: "#/components/schemas/Policy" } } } }
responses:
"201": { description: Created }
"400": { description: Validation error }
/v1/admin/policies/{policyId}:
get:
tags: [Admin]
summary: Get policy
parameters: [{ name: policyId, in: path, required: true, schema: { type: string } }]
responses:
"200": { description: Policy }
"404": { description: Not found }
put:
tags: [Admin]
summary: Update policy
operationId: updatePolicy
parameters: [{ name: policyId, in: path, required: true, schema: { type: string } }]
requestBody:
{ content: { "application/json": { schema: { $ref: "#/components/schemas/Policy" } } } }
responses:
"200": { description: Updated }
"404": { description: Not found }
delete:
tags: [Admin]
summary: Delete policy
operationId: deletePolicy
parameters: [{ name: policyId, in: path, required: true, schema: { type: string } }]
responses:
"204": { description: Deleted }
"404": { description: Not found }
components:
schemas:
# --- Resolver request/response (aligned with data-model and resolution-algorithm) ---
ResolveRequest:
type: object
required: [identifiers]
properties:
identifiers:
type: array
minItems: 1
items: { $ref: "#/components/schemas/IdentifierInput" }
serviceContext:
$ref: "#/components/schemas/ServiceContext"
constraints:
$ref: "#/components/schemas/ResolveConstraints"
tenant: { type: string, description: "Tenant scope for resolution" }
desiredProtocols:
type: array
items: { type: string }
description: "Preferred protocol domains (e.g. as4, ss7, peppol)"
IdentifierInput:
type: object
required: [type, value]
properties:
type:
{
type: string,
description: "Identifier type (e.g. as4.partyId, e164, peppol.participantId)",
}
value: { type: string }
scope: { type: string }
ServiceContext:
type: object
description: |
For ISO 20022 FI-to-FI (profile as4.fifi.iso20022.v1), service = `iso20022.fi` and action is one of
credit.transfer, fi.credit.transfer, payment.status, payment.cancellation, resolution.of.investigation, statement, notification.
properties:
service: { type: string }
action: { type: string }
process: { type: string }
documentType: { type: string }
ResolveConstraints:
type: object
properties:
trustDomain: { type: string }
region: { type: string }
jurisdiction: { type: string }
maxResults: { type: integer, minimum: 1 }
networkBrand:
type: string
description: "Card network (visa, mastercard, amex, discover, diners)"
tenantContract: { type: string, description: "Tenant contract for routing" }
connectivityGroup: { type: string }
requiredCapability: { type: string }
messageType: { type: string, description: "e.g. ISO8583 MTI or AS4 service/action" }
ResolveResponse:
type: object
required: [directives]
properties:
primary: { $ref: "#/components/schemas/RouteDirective" }
alternates:
type: array
items: { $ref: "#/components/schemas/DirectiveWithReason" }
directives:
type: array
items: { $ref: "#/components/schemas/RouteDirective" }
ttl: { type: integer, description: "Cache TTL in seconds" }
traceId: { type: string, format: uuid }
correlationId: { type: string }
failure_policy: { $ref: "#/components/schemas/FailurePolicy" }
negative_cache_ttl: { type: integer, description: "TTL for negative cache when no match" }
resolution_trace:
type: array
items: { $ref: "#/components/schemas/ResolutionTraceEntry" }
DirectiveWithReason:
type: object
required: [directive]
properties:
directive: { $ref: "#/components/schemas/RouteDirective" }
reason: { type: string }
FailurePolicy:
type: object
properties:
retry: { type: boolean }
backoff: { type: string }
circuitBreak: { type: boolean }
ResolutionTraceEntry:
type: object
properties:
source: { type: string }
directiveIndex: { type: integer }
message: { type: string }
RouteDirective:
description: "Normalized routing output; see architecture/route-directive.md and route-directive.schema.json"
type: object
required: [target_protocol, target_address]
properties:
target_protocol: { type: string }
target_address: { type: string }
transport_profile: { type: string }
security:
type: object
properties:
signRequired: { type: boolean }
encryptRequired: { type: boolean }
keyRefs: { type: array, items: { type: string } }
algorithms: { type: object }
service_context:
type: object
properties:
service: { type: string }
action: { type: string }
serviceIndicator: { type: string }
qos:
type: object
properties:
retries: { type: integer }
receiptsRequired: { type: boolean }
ordering: { type: string }
ttl_seconds: { type: integer }
evidence:
oneOf:
- type: object
properties:
source: { type: string }
lastVerified: { type: string, format: date-time }
confidenceScore: { type: number }
signature: { type: string }
- type: array
items:
type: object
properties:
source: { type: string }
freshness: { type: string, format: date-time }
confidence: { type: number }
signature: { type: string }
# --- Admin entities (aligned with data-model) ---
Tenant:
type: object
properties:
id: { type: string }
name: { type: string }
createdAt: { type: string, format: date-time }
updatedAt: { type: string, format: date-time }
Participant:
type: object
properties:
id: { type: string }
tenantId: { type: string }
name: { type: string }
createdAt: { type: string, format: date-time }
updatedAt: { type: string, format: date-time }
Identifier:
type: object
properties:
id: { type: string }
participantId: { type: string }
identifier_type: { type: string }
value: { type: string }
scope: { type: string }
priority: { type: integer }
verified_at: { type: string, format: date-time }
Endpoint:
type: object
properties:
id: { type: string }
participantId: { type: string }
protocol: { type: string }
address: { type: string }
profile: { type: string }
priority: { type: integer }
status: { type: string, enum: [active, inactive, draining] }
CredentialRef:
type: object
properties:
id: { type: string }
participantId: { type: string }
credential_type: { type: string, enum: [tls, sign, encrypt] }
vault_ref: { type: string }
fingerprint: { type: string }
valid_from: { type: string, format: date-time }
valid_to: { type: string, format: date-time }
Policy:
type: object
properties:
id: { type: string }
tenantId: { type: string }
rule_json: { type: object, description: "ABAC rule" }
effect: { type: string, enum: [allow, deny] }
priority: { type: integer }