{
  "openapi": "3.1.0",
  "info": {
    "title": "Teria Sandbox Telemetry API — V2 compatibility",
    "version": "2.0.0",
    "description": "V2 is retained for existing integrations that use Teria routing configuration. Use the V3 contract for new telemetry integrations.\n\nVerify your institution credential with GET /v1/telemetry/connection before sending telemetry.\n\nSubmit institution-scoped observations of payments routed by your institution. This API does not execute payments or change routing. Examples contain synthetic identifiers: replace them with the values supplied during onboarding. Credentials have no automatic expiry; revocation and rotation can retire them. Sandbox credentials cannot authorize production requests."
  },
  "paths": {
    "/v1/telemetry/connection": {
      "get": {
        "operationId": "verifyTelemetryConnection",
        "description": "Verify your institution credential with GET /v1/telemetry/connection before sending telemetry.\n\nAuthenticate without submitting payment telemetry. A successful check records the connection-verification milestone and confirms customer account, canonical institution and environment. Organisation and connection metadata are null for a direct institution. It does not establish that an outcome has been processed.",
        "security": [
          {
            "ingestionCredential": []
          }
        ],
        "responses": {
          "200": {
            "description": "The credential authorizes this customer account, institution and environment. Organization and connection metadata are null for direct institutions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "account_id",
                    "institution_id",
                    "organization_id",
                    "connected_institution_id",
                    "environment",
                    "verified"
                  ],
                  "properties": {
                    "account_id": {
                      "type": "string"
                    },
                    "institution_id": {
                      "type": "string"
                    },
                    "organization_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "connected_institution_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "environment": {
                      "type": "string",
                      "enum": [
                        "sandbox",
                        "production"
                      ]
                    },
                    "verified": {
                      "const": true
                    }
                  }
                },
                "examples": {
                  "organizationInstitution": {
                    "summary": "Institution connected through an organisation",
                    "value": {
                      "account_id": "example-account",
                      "institution_id": "example-origin",
                      "organization_id": "example-organization",
                      "connected_institution_id": "example-institution",
                      "environment": "sandbox",
                      "verified": true
                    }
                  },
                  "directInstitution": {
                    "summary": "Direct institution without a parent organisation",
                    "value": {
                      "account_id": "example-direct-account",
                      "institution_id": "example-origin",
                      "organization_id": null,
                      "connected_institution_id": null,
                      "environment": "sandbox",
                      "verified": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Problem"
          },
          "403": {
            "$ref": "#/components/responses/Problem"
          },
          "500": {
            "$ref": "#/components/responses/Problem"
          },
          "503": {
            "$ref": "#/components/responses/Problem"
          }
        },
        "tags": [
          "Connection"
        ],
        "summary": "Verify institution credential scope",
        "x-teria-availability": "available"
      }
    },
    "/v1/telemetry/batches": {
      "post": {
        "operationId": "acceptTelemetryBatch",
        "security": [
          {
            "ingestionCredential": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TelemetryBatchV2"
              },
              "examples": {
                "legacyV2": {
                  "summary": "V2 attempt with routing configuration version",
                  "value": {
                    "schema_version": 2,
                    "batch_id": "a343d973-6e69-4427-9171-b043e160587d",
                    "sent_at": "2026-10-22T12:00:00.000Z",
                    "events": [
                      {
                        "event_id": "349698d3-e52b-4c16-a3c3-33217146eb25",
                        "transaction_id": "example-transaction-001",
                        "attempt_id": "example-attempt-001",
                        "destination_institution_id": "example-destination",
                        "payment_capability": "interbank_transfer",
                        "switch_id": "nibss",
                        "nibss_technology": "nip",
                        "occurred_at": "2026-10-22T12:00:00.000Z",
                        "kind": "attempt_succeeded",
                        "latency_ms": 284,
                        "connected_institution_id": "example-institution",
                        "schema_version": 2,
                        "routing_config_version": 1
                      }
                    ],
                    "organization_id": "example-organization",
                    "environment": "sandbox"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Events are durably accepted. This does not confirm asynchronous processing. Identical retries are counted as duplicates.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TelemetryAcceptance"
                },
                "example": {
                  "batch_id": "a343d973-6e69-4427-9171-b043e160587d",
                  "accepted_event_count": 1,
                  "duplicate_event_count": 0,
                  "queue_message_count": 1,
                  "accepted_at": "2026-10-22T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "Invalid JSON/schema, repeated IDs within the batch, unsupported directory IDs or V3 event timestamps outside the accepted range. Correct the request before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "properties": {
                    "type": {
                      "type": "string",
                      "format": "uri"
                    },
                    "title": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "detail": {
                      "type": "string"
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "path",
                          "code",
                          "message"
                        ],
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, revoked or retired credential. Obtain valid access before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "properties": {
                    "type": {
                      "type": "string",
                      "format": "uri"
                    },
                    "title": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "detail": {
                      "type": "string"
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "path",
                          "code",
                          "message"
                        ],
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Telemetry access is paused/disabled or the request is outside the authorized scope. Keep buffered events and contact your Teria administrator.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "properties": {
                    "type": {
                      "type": "string",
                      "format": "uri"
                    },
                    "title": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "detail": {
                      "type": "string"
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "path",
                          "code",
                          "message"
                        ],
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "V3 event ID already exists with different immutable content. Preserve the original observation; use a new event ID only for a genuinely new observation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "properties": {
                    "type": {
                      "type": "string",
                      "format": "uri"
                    },
                    "title": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "detail": {
                      "type": "string"
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "path",
                          "code",
                          "message"
                        ],
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "JSON request exceeds 1 MiB. Split into smaller batches without changing event IDs or content.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "properties": {
                    "type": {
                      "type": "string",
                      "format": "uri"
                    },
                    "title": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "detail": {
                      "type": "string"
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "path",
                          "code",
                          "message"
                        ],
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Request rate limited. Back off with jitter; honor Retry-After when supplied.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "properties": {
                    "type": {
                      "type": "string",
                      "format": "uri"
                    },
                    "title": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "detail": {
                      "type": "string"
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "path",
                          "code",
                          "message"
                        ],
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Temporary server failure. Retry with backoff using the same immutable events.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "properties": {
                    "type": {
                      "type": "string",
                      "format": "uri"
                    },
                    "title": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "detail": {
                      "type": "string"
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "path",
                          "code",
                          "message"
                        ],
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Ingestion is temporarily unavailable or not fully accepted. Some events may have been queued; retry the same immutable events with backoff.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "properties": {
                    "type": {
                      "type": "string",
                      "format": "uri"
                    },
                    "title": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "detail": {
                      "type": "string"
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "path",
                          "code",
                          "message"
                        ],
                        "properties": {
                          "path": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Telemetry"
        ],
        "summary": "Submit configured-route telemetry (V2)",
        "x-teria-availability": "available",
        "description": "Compatibility reference for existing V2 integrations.\n\nUse the same endpoint for one outcome or a batch: put one to 1,000 events in the events array, within a 1 MiB JSON request. Every event must belong to the credential's institution and customer account. V2 retains its required organisation, environment and connected-institution fields; they must match the credential. V3 accepts outcomes without earlier lifecycle events or Teria routing configuration. Destinations and switches must be enabled IDs supplied by Teria. V3 events may be at most seven days old or five minutes in the future. Unknown fields are rejected; exclude personal data.\n\nValidation, scope and immutable-content conflicts reject the whole batch before enqueue. A temporary delivery failure may occur after some events were queued: retry the same immutable event IDs and content with backoff. A 202 response confirms durable acceptance, not successful processing. Confirm the first processed outcome in your workspace with your Teria administrator."
      }
    }
  },
  "components": {
    "schemas": {
      "TelemetryBatchV2": {
        "title": "TelemetryBatchV2",
        "description": "A durable-ingestion batch of pseudonymous transaction lifecycle observations.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schema_version",
          "batch_id",
          "organization_id",
          "environment",
          "sent_at",
          "events"
        ],
        "properties": {
          "batch_id": {
            "type": "string",
            "format": "uuid",
            "description": "A UUID identifying this submission batch. Event IDs provide deduplication; changing batch metadata does not create new events."
          },
          "organization_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "description": "Your organisation identifier assigned during onboarding. Must match the credential scope."
          },
          "environment": {
            "type": "string",
            "enum": [
              "local",
              "sandbox",
              "production"
            ],
            "description": "Use sandbox for the sandbox API. Production uses a separate environment and credentials."
          },
          "sent_at": {
            "type": "string",
            "format": "date-time",
            "description": "When you prepared this batch, as an RFC 3339 timestamp. This does not replace the individual event occurrence times."
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "maxItems": 1000,
            "items": {
              "$ref": "#/components/schemas/TelemetryBatchV2/$defs/telemetry_event"
            },
            "description": "One to 1,000 events for a single institution. The entire JSON request must also fit within 1 MiB."
          },
          "schema_version": {
            "const": 2,
            "description": "Payload contract version; independent of the /v1 endpoint path."
          }
        },
        "$defs": {
          "telemetry_event": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/TelemetryBatchV2/$defs/transaction_received_event"
              },
              {
                "$ref": "#/components/schemas/TelemetryBatchV2/$defs/nibss_attempt_event"
              },
              {
                "$ref": "#/components/schemas/TelemetryBatchV2/$defs/other_switch_attempt_event"
              }
            ]
          },
          "transaction_received_event": {
            "title": "TransactionReceivedEventV2",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "schema_version",
              "event_id",
              "transaction_id",
              "connected_institution_id",
              "destination_institution_id",
              "payment_capability",
              "kind",
              "occurred_at"
            ],
            "properties": {
              "schema_version": {
                "const": 2,
                "description": "Payload contract version; independent of the /v1 endpoint path."
              },
              "event_id": {
                "type": "string",
                "format": "uuid",
                "description": "Generate a UUID once per immutable observation. Reuse the same ID and event content on retries. A later outcome is a new observation with a new ID."
              },
              "transaction_id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 128,
                "description": "Your opaque transaction reference, stable across its payment attempts. Do not include account numbers or personal information."
              },
              "connected_institution_id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "description": "The institution identifier assigned during onboarding. Every event in this batch must match the credential scope."
              },
              "destination_institution_id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "description": "An enabled destination identifier supplied by Teria. Obtain the current directory mapping during onboarding; do not substitute a bank name or bank code."
              },
              "kind": {
                "const": "transaction_received",
                "description": "The observation type. An attempt outcome alone is sufficient in V3; transaction_received and attempt_started are optional additions."
              },
              "occurred_at": {
                "type": "string",
                "format": "date-time",
                "description": "When this observation occurred, as an RFC 3339 timestamp. V3 accepts at most seven days old and five minutes in the future. Use millisecond precision."
              },
              "amount_minor": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "description": "Optional integer amount in minor currency units. In V3, provide currency together with amount_minor, or omit both."
              },
              "currency": {
                "type": "string",
                "pattern": "^[A-Z]{3}$",
                "description": "Optional three-letter uppercase currency code. In V3, provide amount_minor together with currency, or omit both."
              },
              "payment_capability": {
                "const": "interbank_transfer",
                "description": "The capability observed by this contract. Currently interbank_transfer."
              }
            }
          },
          "nibss_attempt_event": {
            "title": "NibssAttemptEventV2",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "schema_version",
              "event_id",
              "transaction_id",
              "attempt_id",
              "connected_institution_id",
              "destination_institution_id",
              "payment_capability",
              "switch_id",
              "kind",
              "occurred_at",
              "routing_config_version",
              "nibss_technology"
            ],
            "properties": {
              "schema_version": {
                "const": 2,
                "description": "Payload contract version; independent of the /v1 endpoint path."
              },
              "event_id": {
                "type": "string",
                "format": "uuid",
                "description": "Generate a UUID once per immutable observation. Reuse the same ID and event content on retries. A later outcome is a new observation with a new ID."
              },
              "transaction_id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 128,
                "description": "Your opaque transaction reference, stable across its payment attempts. Do not include account numbers or personal information."
              },
              "attempt_id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 128,
                "description": "Your opaque reference for one actual payment attempt. A payment retry creates a new attempt under the same transaction."
              },
              "connected_institution_id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "description": "The institution identifier assigned during onboarding. Every event in this batch must match the credential scope."
              },
              "destination_institution_id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "description": "An enabled destination identifier supplied by Teria. Obtain the current directory mapping during onboarding; do not substitute a bank name or bank code."
              },
              "switch_id": {
                "const": "nibss",
                "description": "The enabled switch that actually handled the attempt. Teria supplies supported identifiers during onboarding."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "attempt_started",
                  "attempt_succeeded",
                  "attempt_failed",
                  "attempt_timed_out",
                  "attempt_reversed"
                ],
                "description": "The observation type. An attempt outcome alone is sufficient in V3; transaction_received and attempt_started are optional additions."
              },
              "occurred_at": {
                "type": "string",
                "format": "date-time",
                "description": "When this observation occurred, as an RFC 3339 timestamp. V3 accepts at most seven days old and five minutes in the future. Use millisecond precision."
              },
              "latency_ms": {
                "type": "integer",
                "minimum": 0,
                "maximum": 2147483647,
                "description": "Optional measured attempt latency in whole milliseconds. Omit if not measured; do not send a guessed zero."
              },
              "response_code": {
                "type": "string",
                "minLength": 1,
                "maxLength": 32,
                "description": "Optional non-personal switch response code."
              },
              "amount_minor": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "description": "Optional integer amount in minor currency units. In V3, provide currency together with amount_minor, or omit both."
              },
              "currency": {
                "type": "string",
                "pattern": "^[A-Z]{3}$",
                "description": "Optional three-letter uppercase currency code. In V3, provide amount_minor together with currency, or omit both."
              },
              "payment_capability": {
                "const": "interbank_transfer",
                "description": "The capability observed by this contract. Currently interbank_transfer."
              },
              "routing_config_version": {
                "type": "integer",
                "minimum": 1,
                "description": "V2 compatibility field: the Teria routing allocation version that governed this attempt. V3 does not accept this field."
              },
              "nibss_technology": {
                "type": "string",
                "enum": [
                  "nip",
                  "nps"
                ],
                "description": "Required only for the nibss switch: nip or nps. Report the technology actually used."
              }
            }
          },
          "other_switch_attempt_event": {
            "title": "OtherSwitchAttemptEventV2",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "schema_version",
              "event_id",
              "transaction_id",
              "attempt_id",
              "connected_institution_id",
              "destination_institution_id",
              "payment_capability",
              "switch_id",
              "kind",
              "occurred_at",
              "routing_config_version"
            ],
            "properties": {
              "schema_version": {
                "const": 2,
                "description": "Payload contract version; independent of the /v1 endpoint path."
              },
              "event_id": {
                "type": "string",
                "format": "uuid",
                "description": "Generate a UUID once per immutable observation. Reuse the same ID and event content on retries. A later outcome is a new observation with a new ID."
              },
              "transaction_id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 128,
                "description": "Your opaque transaction reference, stable across its payment attempts. Do not include account numbers or personal information."
              },
              "attempt_id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 128,
                "description": "Your opaque reference for one actual payment attempt. A payment retry creates a new attempt under the same transaction."
              },
              "connected_institution_id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "description": "The institution identifier assigned during onboarding. Every event in this batch must match the credential scope."
              },
              "destination_institution_id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "description": "An enabled destination identifier supplied by Teria. Obtain the current directory mapping during onboarding; do not substitute a bank name or bank code."
              },
              "switch_id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "pattern": "^(?!nibss$).+",
                "description": "The enabled switch that actually handled the attempt. Teria supplies supported identifiers during onboarding."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "attempt_started",
                  "attempt_succeeded",
                  "attempt_failed",
                  "attempt_timed_out",
                  "attempt_reversed"
                ],
                "description": "The observation type. An attempt outcome alone is sufficient in V3; transaction_received and attempt_started are optional additions."
              },
              "occurred_at": {
                "type": "string",
                "format": "date-time",
                "description": "When this observation occurred, as an RFC 3339 timestamp. V3 accepts at most seven days old and five minutes in the future. Use millisecond precision."
              },
              "latency_ms": {
                "type": "integer",
                "minimum": 0,
                "maximum": 2147483647,
                "description": "Optional measured attempt latency in whole milliseconds. Omit if not measured; do not send a guessed zero."
              },
              "response_code": {
                "type": "string",
                "minLength": 1,
                "maxLength": 32,
                "description": "Optional non-personal switch response code."
              },
              "amount_minor": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "description": "Optional integer amount in minor currency units. In V3, provide currency together with amount_minor, or omit both."
              },
              "currency": {
                "type": "string",
                "pattern": "^[A-Z]{3}$",
                "description": "Optional three-letter uppercase currency code. In V3, provide amount_minor together with currency, or omit both."
              },
              "payment_capability": {
                "const": "interbank_transfer",
                "description": "The capability observed by this contract. Currently interbank_transfer."
              },
              "routing_config_version": {
                "type": "integer",
                "minimum": 1,
                "description": "V2 compatibility field: the Teria routing allocation version that governed this attempt. V3 does not accept this field."
              }
            }
          }
        }
      },
      "TelemetryAcceptance": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "batch_id",
          "accepted_event_count",
          "duplicate_event_count",
          "queue_message_count",
          "accepted_at"
        ],
        "properties": {
          "batch_id": {
            "type": "string",
            "format": "uuid"
          },
          "accepted_event_count": {
            "type": "integer",
            "minimum": 0
          },
          "duplicate_event_count": {
            "type": "integer",
            "minimum": 0
          },
          "queue_message_count": {
            "type": "integer",
            "minimum": 0
          },
          "accepted_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    },
    "securitySchemes": {
      "ingestionCredential": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "<credential-id>.<secret>",
        "description": "Institution-scoped credential issued by a Teria administrator. Send credential_id.secret as the bearer value. The secret is shown once and delivered separately; never put it in a URL or shared collection. Credentials do not automatically expire. During rotation the old credential is retired within 24 hours or earlier when cutover is confirmed."
      }
    },
    "responses": {
      "Problem": {
        "description": "RFC 9457 problem details.",
        "content": {
          "application/problem+json": {
            "schema": {
              "type": "object",
              "required": [
                "type",
                "title",
                "status",
                "detail"
              ],
              "properties": {
                "type": {
                  "type": "string",
                  "format": "uri"
                },
                "title": {
                  "type": "string"
                },
                "status": {
                  "type": "integer"
                },
                "detail": {
                  "type": "string"
                },
                "request_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "errors": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "path",
                      "code",
                      "message"
                    ],
                    "properties": {
                      "path": {
                        "type": "string"
                      },
                      "code": {
                        "type": "string"
                      },
                      "message": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "servers": [
    {
      "url": "https://sandbox.teriahq.com",
      "description": "Sandbox — test telemetry only"
    }
  ],
  "tags": [
    {
      "name": "Telemetry",
      "description": "Durably submit payment attempt observations."
    },
    {
      "name": "Connection",
      "description": "Check the scope of an institution credential."
    }
  ],
  "externalDocs": {
    "url": "https://developers.teriahq.com/quickstart.html",
    "description": "Sandbox integration quickstart"
  }
}
