> ## Documentation Index
> Fetch the complete documentation index at: https://doc.raliopay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Related Party KYC Session Created

> Webhook event fired when a KYC verification session is created for a related party of a business user

<Info>
  **Event Name:** `related_party.kyc_session_created`
</Info>

<Note>
  This event is fired when the onboarding team creates a KYC verification session for a related party (Shareholder, UBO or Authorized Representative) of a business user. Use it to inform the related party — usually via email — that they need to complete the verification before the session expires. The session state at this point is always `NOT_STARTED`, which is reflected as `KYC_PENDING` on the related party.
</Note>

## Event Payload

The webhook payload contains the following structure:

```json Example Payload theme={null}
{
  "eventId": "8fbb9c6a-1f4c-4b3f-9b4a-c0fda4c3e3a1",
  "eventType": "related_party.kyc_session_created",
  "timestamp": "2026-04-29T12:50:22.227Z",
  "data": {
    "businessUser": {
      "id": 1234,
      "name": "Acme Corp S.L."
    },
    "relatedParty": {
      "id": "f6c8c8c8-1234-4abc-9def-0123456789ab",
      "roleType": "UBO",
      "firstName": "John",
      "lastName": "Doe",
      "email": "john.doe@example.com",
      "phoneNumber": "+34911223344",
      "nationality": "ES",
      "ownershipPercentage": 30,
      "residentialAddress": {
        "addressLine1": "123 Main Street",
        "city": "Madrid",
        "provinceState": "Madrid",
        "postalCode": "28001",
        "country": "ES"
      },
      "status": "KYC_PENDING"
    },
    "kycSession": {
      "id": "a1b2c3d4-5678-49ab-9cde-f0123456789a",
      "provider": "mati",
      "url": "https://signup.getmati.com/?merchantToken=...&flowId=...",
      "expiresAt": "2026-05-06T12:50:22.227Z"
    }
  }
}
```

## Field Description

<ParamField path="eventId" type="string" required>
  Unique event identifier (UUID).
</ParamField>

<ParamField path="eventType" type="string" required>
  Event type — always `related_party.kyc_session_created` for this webhook.
</ParamField>

<ParamField path="timestamp" type="string" required>
  Event timestamp in ISO 8601 format.
</ParamField>

<ParamField path="data" type="object" required>
  Contains the event data.
</ParamField>

<ParamField path="data.businessUser" type="object" required>
  Business user that the related party belongs to.
</ParamField>

<ParamField path="data.businessUser.id" type="integer" required>
  Internal numeric identifier of the business user.
</ParamField>

<ParamField path="data.businessUser.name" type="string" required>
  Legal name of the business user.
</ParamField>

<ParamField path="data.relatedParty" type="object" required>
  Related party for whom the KYC session was created.
</ParamField>

<ParamField path="data.relatedParty.id" type="string" required>
  Unique related party identifier (UUID).
</ParamField>

<ParamField path="data.relatedParty.roleType" type="string" required>
  Role of the related party within the business. Possible values: `SHAREHOLDER`, `UBO`, `AUTHORIZED_REPRESENTATIVE`.
</ParamField>

<ParamField path="data.relatedParty.firstName" type="string" required>
  Related party's first name.
</ParamField>

<ParamField path="data.relatedParty.lastName" type="string" required>
  Related party's last name.
</ParamField>

<ParamField path="data.relatedParty.email" type="string" required>
  Email address used to contact the related party for the verification.
</ParamField>

<ParamField path="data.relatedParty.phoneNumber" type="string">
  Related party's phone number, when available.
</ParamField>

<ParamField path="data.relatedParty.nationality" type="string" required>
  ISO 3166-1 alpha-2 country code of the related party's nationality.
</ParamField>

<ParamField path="data.relatedParty.ownershipPercentage" type="integer">
  Percentage of the business owned by the related party. Omitted when not applicable (e.g. authorized representatives).
</ParamField>

<ParamField path="data.relatedParty.residentialAddress" type="object" required>
  Residential address of the related party.
</ParamField>

<ParamField path="data.relatedParty.residentialAddress.addressLine1" type="string" required>
  Street address line.
</ParamField>

<ParamField path="data.relatedParty.residentialAddress.city" type="string" required>
  City.
</ParamField>

<ParamField path="data.relatedParty.residentialAddress.provinceState" type="string" required>
  Province or state.
</ParamField>

<ParamField path="data.relatedParty.residentialAddress.postalCode" type="string" required>
  Postal or ZIP code.
</ParamField>

<ParamField path="data.relatedParty.residentialAddress.country" type="string" required>
  ISO 3166-1 alpha-2 country code.
</ParamField>

<ParamField path="data.relatedParty.status" type="string" required>
  KYC status of the related party at the time the session is created. Always `KYC_PENDING` for this event.
</ParamField>

<ParamField path="data.kycSession" type="object" required>
  Newly created KYC session.
</ParamField>

<ParamField path="data.kycSession.id" type="string" required>
  Unique KYC session identifier (UUID).
</ParamField>

<ParamField path="data.kycSession.provider" type="string" required>
  Identity verification provider. Currently `mati`.
</ParamField>

<ParamField path="data.kycSession.url" type="string" required>
  Hosted URL the related party must visit to complete the verification.
</ParamField>

<ParamField path="data.kycSession.expiresAt" type="string">
  ISO 8601 timestamp at which the session expires. May be omitted when the provider does not return an expiration.
</ParamField>

## Expected Responses

<CardGroup cols={3}>
  <Card title="Success Response" icon="circle-check" color="#16a34a">
    **HTTP 200 OK**

    The webhook was processed successfully.
  </Card>

  <Card title="Client Error" icon="triangle-exclamation" color="#ea580c">
    **HTTP 4xx Status**

    Client-side error. Will not be retried.
  </Card>

  <Card title="Server Error" icon="circle-xmark" color="#dc2626">
    **HTTP 5xx Status**

    Server-side error. Will be retried with exponential backoff.
  </Card>
</CardGroup>

## Implementation Example

<CodeGroup>
  ```javascript Node.js theme={null}
  app.post('/webhooks/ralio', async (req, res) => {
    const { eventType, data } = req.body;

    if (eventType === 'related_party.kyc_session_created') {
      const { businessUser, relatedParty, kycSession } = data;

      console.log(
        `KYC session ${kycSession.id} created for related party ${relatedParty.id} of ${businessUser.name}`,
      );

      await sendKycInvitation({
        to: relatedParty.email,
        verificationUrl: kycSession.url,
        expiresAt: kycSession.expiresAt,
        businessName: businessUser.name,
        relatedPartyName: `${relatedParty.firstName} ${relatedParty.lastName}`,
      });

      res.status(200).json({ received: true });
    }
  });
  ```

  ```python Python theme={null}
  @app.route('/webhooks/ralio', methods=['POST'])
  def handle_webhook():
      payload = request.get_json()

      if payload['eventType'] == 'related_party.kyc_session_created':
          data = payload['data']
          business_user = data['businessUser']
          related_party = data['relatedParty']
          kyc_session = data['kycSession']

          send_kyc_invitation(
              to=related_party['email'],
              verification_url=kyc_session['url'],
              expires_at=kyc_session.get('expiresAt'),
              business_name=business_user['name'],
              related_party_name=f"{related_party['firstName']} {related_party['lastName']}",
          )

          return jsonify({'received': True}), 200
  ```

  ```go Go theme={null}
  func handleWebhook(w http.ResponseWriter, r *http.Request) {
      var payload struct {
          EventType string `json:"eventType"`
          Data      struct {
              BusinessUser struct {
                  ID   uint   `json:"id"`
                  Name string `json:"name"`
              } `json:"businessUser"`
              RelatedParty struct {
                  ID        string `json:"id"`
                  FirstName string `json:"firstName"`
                  LastName  string `json:"lastName"`
                  Email     string `json:"email"`
              } `json:"relatedParty"`
              KycSession struct {
                  ID        string  `json:"id"`
                  URL       string  `json:"url"`
                  ExpiresAt *string `json:"expiresAt,omitempty"`
              } `json:"kycSession"`
          } `json:"data"`
      }

      if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
          http.Error(w, "Invalid JSON", http.StatusBadRequest)
          return
      }

      if payload.EventType == "related_party.kyc_session_created" {
          if err := sendKycInvitation(
              payload.Data.RelatedParty.Email,
              payload.Data.KycSession.URL,
              payload.Data.KycSession.ExpiresAt,
              payload.Data.BusinessUser.Name,
              payload.Data.RelatedParty.FirstName+" "+payload.Data.RelatedParty.LastName,
          ); err != nil {
              http.Error(w, "Internal error", http.StatusInternalServerError)
              return
          }

          w.Header().Set("Content-Type", "application/json")
          w.WriteHeader(http.StatusOK)
          json.NewEncoder(w).Encode(map[string]bool{"received": true})
      }
  }
  ```
</CodeGroup>
