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

# Onboard Partners

> Call this endpoint to onboard partners to UFEL ecosystem

export const EcosystemURLBlock = ({content = [], title = ""}) => {
  return <div style={{
    backgroundColor: "#6B3B900A",
    borderRadius: "8px",
    borderColor: "#F8F8F8"
  }} className="flex flex-col gap-4 border p-6">
      {title && <p className="font-bold text-2xl" style={{
    color: "#1C1C1C",
    marginBlock: "0px"
  }}>
          {title || ""}
        </p>}

      {content.length > 0 && content?.map((el, id) => <div key={id} className="flex flex-col [&>*]:my-0 gap-2">
            <div className="flex items-center justify-between [&>*]:my-0" style={{
    height: "fit-content"
  }}>
              <span className="font-bold" style={{
    color: "#1C1C1CCC",
    marginBlock: "0px"
  }}>
                {el.title}
              </span>
              <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" onClick={async () => {
    await navigator.clipboard.writeText(el.caption);
    alert("Link copied!");
  }}>
                <path d="M6 10C6 8.1144 6 7.1716 6.58579 6.58579C7.1716 6 8.1144 6 10 6H10.6667C12.5523 6 13.4951 6 14.0809 6.58579C14.6667 7.1716 14.6667 8.1144 14.6667 10V10.6667C14.6667 12.5523 14.6667 13.4951 14.0809 14.0809C13.4951 14.6667 12.5523 14.6667 10.6667 14.6667H10C8.1144 14.6667 7.1716 14.6667 6.58579 14.0809C6 13.4951 6 12.5523 6 10.6667V10Z" stroke="#191B1F" stroke-opacity="0.6" stroke-linecap="round" stroke-linejoin="round" />
                <path d="M11.3334 6.00016C11.3318 4.02877 11.302 3.00764 10.7282 2.30845C10.6174 2.17342 10.4936 2.04962 10.3586 1.9388C9.62096 1.3335 8.52516 1.3335 6.3335 1.3335C4.14184 1.3335 3.04602 1.3335 2.30845 1.9388C2.17342 2.04961 2.04962 2.17342 1.9388 2.30845C1.3335 3.04602 1.3335 4.14184 1.3335 6.3335C1.3335 8.52516 1.3335 9.62096 1.9388 10.3586C2.04961 10.4936 2.17342 10.6174 2.30845 10.7282C3.00764 11.302 4.02877 11.3318 6.00016 11.3334" stroke="#191B1F" stroke-opacity="0.6" stroke-linecap="round" stroke-linejoin="round" />
              </svg>
            </div>
            <p className="font-medium text-sm border-none" style={{
    color: el.color || "#1C1C1CCC"
  }}>
              {el.caption}
            </p>
          </div>)}
    </div>;
};

export const Table = ({data = []}) => <div className="text-sm font-mono">
    <div style={{
  gap: 10,
  display: "grid",
  padding: "5px 10px",
  backgroundColor: "#F7F9FB",
  color: "rgba(25,27,31,0.6)",
  gridTemplateColumns: "repeat(3, minmax(0, 1fr))"
}}>
      <span>name</span>
      <span>type</span>
      <span>Description</span>
    </div>
    {data?.map((item, idx) => <div key={idx} style={{
  gap: 10,
  display: "grid",
  padding: "8px 10px",
  color: "rgba(25,27,31,0.8)",
  gridTemplateColumns: "repeat(3, minmax(0, 1fr))"
}}>
        <span className="break-words">{item.name}</span>
        <span>{item.type}</span>
        <span>{item.desc}</span>
      </div>)}
  </div>;

export const NoteStatement = ({label, message}) => <div className="relative text-sm" style={{
  borderRadius: 16,
  padding: "1px 20px",
  backgroundColor: "rgba(252,155,28,.06)"
}}>
    <p style={{
  marginBlock: 0
}}>
      {label && <span>
          <span className="font-bold" style={{
  color: "#fc9b1c"
}}>
            {label || "PS"}
          </span>
          {message && `: `}
        </span>}
      {message}
    </p>
    <div className="absolute left-0 top-1/2 -translate-y-1/2 rounded-e-full" style={{
  width: 2,
  height: 35,
  backgroundColor: "#fc9b1c"
}} />
  </div>;

####

<EcosystemURLBlock
  content={[
{
  title: "URL",
  caption: "https://test-api.bvndle.com/api/v1/ufel/partners",
  color: "#6B3B90",
},
{
  title: "Base URL",
  caption: "https://test-api.bvndle.com/api/v1/ufel/",
  color: "#6B3B90",
},
{
  title: "HTTP Method",
  caption: "POST",
},
]}
/>

###

<Table
  data={[
{
  name: "applicationName",
  type: "string",
  desc: (
    <>
      Required <br />
      The name of the partner's application
    </>
  ),
},
{
  name: "redirectUrl",
  type: "string",
  desc: (
    <>
      Required <br />
      URL to return to after exiting the authorization server. This is the
      default returned redirectUrl (if the deviceType query param is not
      passed when requesting an authorization code). This can be the same
      value as either webRedirectUrl or mobileRedirectUrl
    </>
  ),
},
{
  name: "webRedirectUrl",
  type: "string",
  desc: (
    <>
      Optional <br />
      Web URL to return to after exiting the authorization server.
    </>
  ),
},
{
  name: "mobileRedirectUrl",
  type: "string",
  desc: (
    <>
      Optional <br />
      Mobile URL to return to after exiting the authorization server.
    </>
  ),
},
{
  name: "email",
  type: "string",
  desc: (
    <>
      Required <br />
      the partner email address. To be used for login and password reset
    </>
  ),
},
{
  name: "partnerName",
  type: "string",
  desc: (
    <>
      Required <br />
      The name of the partner
    </>
  ),
},
{
  name: "password",
  type: "string",
  desc: (
    <>
      Required <br />
      Password must contain atleast 8 characters, one uppercase, one number
      and one special case character
    </>
  ),
},
{
  name: "confirmPassword",
  type: "string",
  desc: (
    <>
      Required <br />
      must match password
    </>
  ),
},
{
  name: "userDetailsUrl",
  type: "string",
  desc: (
    <>
      Required <br />
      URL to get user details by tag
    </>
  ),
},
]}
/>

######

<NoteStatement label="NOTE" message="The userDetailsUrl must accept a query parameter of “tag”" />

####

The response data from the userDetailsUrl must follow this user format

```bash typescript theme={null}

{
  id: string;
  fullname: string;
  tag: string;
  avatar: string;
  email: string;
  emailVerified: boolean;
  phone: string;
  dateOfBirth: Date;
  countryCode: string;
  gender: string;
  isAdult: boolean;
  bvn: string;
  accountNumber: string;
  kyc: {
    id: string;
    bvn: string;
    streetAddress: string;
    city: string;
    state: string;
    postalCode: string;
    country: string;
    proofOfAddress: string;
    governmentId: string;
    userPhoto: string;
    bvnProvided: boolean;
    bvnValidated: boolean;
    addressProvided: boolean;
    addressValidated: boolean;
    idProvided: boolean;
    idValidated: boolean;
    isCompleted: boolean;
    verificationStatus: string;
    phone: string;
    phoneVerified: boolean;
    phoneCodeExpiresAt: Date;
  }
}

```

###

```bash cURL theme={null}
curl --request POST
'https://test-api.bvndle.com/api/v1/ufel/partners' \
--header 'Content-Type: application/json' \

{
    "applicationName": "Anchoria",
    "redirectUrl": "webdemoredirect.com",
    "webRedirectUrl": "webdemoredirect.com",
    "mobileRedirectUrl": "mobiledemoredirect.com"
    "email": "example.testpartner4@gmail.com",
    "partnerName": "test partner",
    "password": "testPartner@1",
    "confirmPassword": "testPartner@1",
    "userDetailsUrl": "https://example.anchoria.com/api/v1/users/nesta"
}

```

###

<ResponseExample>
  ```json Success theme={null}
  {
    "status": "success",
    "message": "Partner details saved successfully",
    "data": {
      "id": "64d8ecb0-60d2-46f8-b56a-f85e640fd655",
      "applicationName": "Anchoria",
      "clientId": "f11722107d8425b1e7dd87aeb17e36da7c593ab98114345544cd52267829cae964428fcf61c1072e8c46cd391b4df3bacf6687737d79a79d457cab4bc7231664",
      "webRedirectUrl": "webdemoredirect.com",
      "mobileRedirectUrl": "mobiledemoredirect.com",
      "partnerId": "dd832b19-8ffe-4b27-9bc0-4d9794a86893",
      "redirectUrl": "webdemoredirect.com",
      "email": "example.testpartner4@gmail.com",
      "partnerName": "test partner",
      "userDetailsUrl": "http://example.anchoria.com/api/v1/users/nesta"
    }
  }
  ```

  ```json Error 400 theme={null}
  {
    "status": "failed",
    "message": "invalid data provided",
    "data": {
      "errorType": "invalid",
      "appErrorCode": "Bad request",
      "error": "\"applicationName\" is required"
    }
  }
  ```
</ResponseExample>
