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 }