{
  "openapi": "3.1.0",
  "info": {
    "title": "Teria Sandbox Telemetry API",
    "version": "3.0.0",
    "description": "Use V3 to submit individual attempt outcomes or batches of telemetry from your institution.\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/TelemetryBatchV3"
              },
              "examples": {
                "singleOutcome": {
                  "summary": "One standalone attempt outcome",
                  "value": {
                    "schema_version": 3,
                    "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
                      }
                    ]
                  }
                },
                "batchOutcomes": {
                  "summary": "Two outcomes for the same institution",
                  "value": {
                    "schema_version": 3,
                    "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
                      },
                      {
                        "event_id": "c349733a-76df-488f-8c1e-f9cc9fba2c74",
                        "transaction_id": "example-transaction-002",
                        "attempt_id": "example-attempt-002",
                        "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_timed_out",
                        "latency_ms": 284
                      }
                    ]
                  }
                },
                "fullLifecycle": {
                  "summary": "Optional transaction and attempt-start observations",
                  "value": {
                    "schema_version": 3,
                    "batch_id": "a343d973-6e69-4427-9171-b043e160587d",
                    "sent_at": "2026-10-22T12:00:00.000Z",
                    "events": [
                      {
                        "event_id": "2351a641-1ce5-48db-bc43-dab2fc4dddb8",
                        "transaction_id": "example-transaction-001",
                        "destination_institution_id": "example-destination",
                        "payment_capability": "interbank_transfer",
                        "occurred_at": "2026-10-22T12:00:00.000Z",
                        "kind": "transaction_received"
                      },
                      {
                        "event_id": "0934561f-b08a-4357-bec1-9bb185a326c3",
                        "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_started"
                      },
                      {
                        "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
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "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/TelemetryAcceptanceV3"
                },
                "example": {
                  "request_id": "3c0641cd-5cb2-41bf-aeea-69479c5176f6",
                  "batch_id": "a343d973-6e69-4427-9171-b043e160587d",
                  "accepted_event_count": 1,
                  "duplicate_event_count": 0,
                  "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 attempt outcomes (V3)",
        "x-teria-availability": "available",
        "description": "Use V3 to submit individual attempt outcomes or batches of telemetry from your institution.\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. The API derives customer account and originating institution from the credential and environment from the deployment. Direct institutions do not need a parent organisation. Omit organization_id, environment and connected_institution_id; existing integrations may supply them as matching compatibility assertions. 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": {
      "TelemetryBatchV3": {
        "title": "TelemetryBatchV3",
        "description": "Institution-scoped telemetry observations; attempt outcomes are sufficient without routing configuration.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schema_version",
          "batch_id",
          "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": "Optional compatibility assertion. V3 derives the customer account and any organization from the credential. If supplied, this must match that organization. Omit for direct institutions."
          },
          "environment": {
            "type": "string",
            "enum": [
              "sandbox",
              "production"
            ],
            "description": "Optional compatibility assertion. The API deployment determines environment and accepts only matching credentials. Omit this field in V3; any supplied value must match the credential and deployment."
          },
          "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/TelemetryBatchV3/$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": 3,
            "description": "Payload contract version; independent of the /v1 endpoint path."
          }
        },
        "$defs": {
          "telemetry_event": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/TelemetryBatchV3/$defs/transaction_received_event"
              },
              {
                "$ref": "#/components/schemas/TelemetryBatchV3/$defs/nibss_attempt_event"
              },
              {
                "$ref": "#/components/schemas/TelemetryBatchV3/$defs/other_switch_attempt_event"
              }
            ]
          },
          "transaction_received_event": {
            "title": "TransactionReceivedEventV3",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "event_id",
              "transaction_id",
              "destination_institution_id",
              "payment_capability",
              "kind",
              "occurred_at"
            ],
            "properties": {
              "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": "Optional compatibility assertion. V3 derives the originating institution from the credential. If supplied, this must match the credential connection. Omit for direct institutions."
              },
              "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."
              }
            },
            "dependentRequired": {
              "amount_minor": [
                "currency"
              ],
              "currency": [
                "amount_minor"
              ]
            }
          },
          "nibss_attempt_event": {
            "title": "NibssAttemptEventV3",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "event_id",
              "transaction_id",
              "attempt_id",
              "destination_institution_id",
              "payment_capability",
              "switch_id",
              "kind",
              "occurred_at",
              "nibss_technology"
            ],
            "properties": {
              "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": "Optional compatibility assertion. V3 derives the originating institution from the credential. If supplied, this must match the credential connection. Omit for direct institutions."
              },
              "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."
              },
              "nibss_technology": {
                "type": "string",
                "enum": [
                  "nip",
                  "nps"
                ],
                "description": "Required only for the nibss switch: nip or nps. Report the technology actually used."
              }
            },
            "dependentRequired": {
              "amount_minor": [
                "currency"
              ],
              "currency": [
                "amount_minor"
              ]
            }
          },
          "other_switch_attempt_event": {
            "title": "OtherSwitchAttemptEventV3",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "event_id",
              "transaction_id",
              "attempt_id",
              "destination_institution_id",
              "payment_capability",
              "switch_id",
              "kind",
              "occurred_at"
            ],
            "properties": {
              "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": "Optional compatibility assertion. V3 derives the originating institution from the credential. If supplied, this must match the credential connection. Omit for direct institutions."
              },
              "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."
              }
            },
            "dependentRequired": {
              "amount_minor": [
                "currency"
              ],
              "currency": [
                "amount_minor"
              ]
            }
          }
        }
      },
      "TelemetryAcceptanceV3": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "request_id",
          "batch_id",
          "accepted_event_count",
          "duplicate_event_count",
          "accepted_at"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid"
          },
          "batch_id": {
            "type": "string",
            "format": "uuid"
          },
          "accepted_event_count": {
            "type": "integer",
            "minimum": 0
          },
          "duplicate_event_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"
  }
}
