Ry2254
Ry2254

Reputation: 1009

Signature Tab and Text Tab not appearing in the DocUSign recipient view Contract?

I have a template which I created in the docusign UI. When I eventually get the recipient view URL comes back and I put it in the url. The text and signature tabs are not visible in the contract unless I use the log in details I signed up to DocUSign with.

In this example, lets say my sign up details are:

In the first code example below, wthe recipient view does not allow me to sign the contract.

In the second code example below, I am allowed to sign the contract. It's like DocUSign seems to know it is me viewing the document despite me being in incognito mode.

The only different between the two below code examples is the requestData where the latter has an additional role using the login in details I signed up with.

It is worth noting that:

email: "[email protected]", name: "fullstackryan",

Doesn't have a DocUSign account but guess this doesn't matter? Because we don't want to have to force our clients to sign up first?

import { NextResponse } from "next/server";
import axios, { AxiosResponse } from "axios";
import { convertPenniesToPounds } from "@/lib/convertPenniesToPounds";

type TextTab = {
  anchorString: string;
  anchorUnits: string;
  anchorXOffset: string;
  anchorYOffset: string;
  tabLabel: string;
  width?: string;
  value?: string;
};

type TemplateRole = {
  email: string;
  name: string;
  roleName: string;
  tabs?: {
    signHereTabs?: TextTab[];
    textTabs?: TextTab[];
  };
};

type RequestData = {
  templateId: string;
  templateRoles: TemplateRole[];
  status: string;
};

const createEnvelope = async (
  templateId: string,
  signerEmail: string,
  signerName: string,
  renewalPrice: string
): Promise<any> => {
  const requestData: RequestData = {
    templateId,
    templateRoles: [
      {
        email: "[email protected]",
        name: "fullstackryan",
        roleName: "placeholder",
        tabs: {
          signHereTabs: [
            {
              anchorString: "/XSIGNHEREX/",
              anchorUnits: "pixels",
              anchorXOffset: "20",
              anchorYOffset: "10",
              tabLabel: "signHere",
            },
          ],
          textTabs: [
            {
              anchorString: "/LegalRenewalPrice/",
              anchorUnits: "pixels",
              anchorXOffset: "20",
              anchorYOffset: "10",
              tabLabel: "renewalPrice",
              width: "100",
              value: renewalPrice,
            },
          ],
        },
      },
    ],
    status: "sent",
  };

  const config = {
    headers: {
      Authorization: `Bearer ${process.env.DOCUSIGN_ACCESS_TOKEN}`,
      "Content-Type": "application/json",
    },
  };

  try {
    const response = await axios.post(
      `${process.env.DOCUSIGN_BASE_URI}accounts/${process.env.DOCUSIGN_API_ACCOUNT_ID}/envelopes`,
      requestData,
      config
    );
    return response.data;
  } catch (error) {
    console.error("Error sending request:", error);
    throw error;
  }
};

const createRecipientView = async (
  envelopeId: string,
  accountId: string,
  returnUrl: string,
  userName: string,
  userEmail: string
): Promise<AxiosResponse> => {
  const requestData = {
    returnUrl,
    authenticationMethod: "None",
    email: userEmail,
    userName,
  };

  const config = {
    headers: {
      Authorization: `Bearer ${process.env.DOCUSIGN_ACCESS_TOKEN}`,
      "Content-Type": "application/json",
    },
  };

  try {
    const response = await axios.post(
      `${process.env.DOCUSIGN_BASE_URI}accounts/${accountId}/envelopes/${envelopeId}/views/recipient`,
      requestData,
      config
    );

    return response.data.url;
  } catch (error) {
    console.error("Error creating recipient view:", error);
    throw error;
  }
};

export async function POST(request: Request) {
  const { templateId, name, email, renewalPrice } = await request.json();
  try {
    const data = await createEnvelope(
      templateId,
      "[email protected]",
      "fullstackryan",
      convertPenniesToPounds(renewalPrice)
    );

    const viewUrl = await createRecipientView(
      data.envelopeId,
      `${process.env.DOCUSIGN_API_ACCOUNT_ID}`,
      "http://localhost:3000/",
      "fullstackryan", // what's username for and where does it come
      "[email protected]"
    );

    return NextResponse.json({
      recipientView: viewUrl,
      envelopeId: data.envelopeId,
    });
  } catch (error) {
    console.error("Failed to send the request:", error);
    return NextResponse.json({ error: "Failed to send the request" });
  }
}

Second code example below:

import { NextResponse } from "next/server";
import axios, { AxiosResponse } from "axios";
import { convertPenniesToPounds } from "@/lib/convertPenniesToPounds";

type TextTab = {
  anchorString: string;
  anchorUnits: string;
  anchorXOffset: string;
  anchorYOffset: string;
  tabLabel: string;
  width?: string;
  value?: string;
};

type TemplateRole = {
  email: string;
  name: string;
  roleName: string;
  tabs?: {
    signHereTabs?: TextTab[];
    textTabs?: TextTab[];
  };
};

type RequestData = {
  templateId: string;
  templateRoles: TemplateRole[];
  status: string;
};

const createEnvelope = async (
  templateId: string,
  signerEmail: string,
  signerName: string,
  renewalPrice: string
): Promise<any> => {
  const requestData: RequestData = {
    templateId,
    templateRoles: [
      {
        email: "[email protected]",
        name: "fullstackryan",
        roleName: "placeholder",
        tabs: {
          signHereTabs: [
            {
              anchorString: "/XSIGNHEREX/",
              anchorUnits: "pixels",
              anchorXOffset: "20",
              anchorYOffset: "10",
              tabLabel: "signHere",
            },
          ],
          textTabs: [
            {
              anchorString: "/XLEGALRENEWALPRICEX/",
              anchorUnits: "pixels",
              anchorXOffset: "20",
              anchorYOffset: "10",
              tabLabel: "renewalPrice",
              width: "100",
              value: renewalPrice,
            },
          ],
        },
      },
      {
        email: "[email protected]",
        name: "Ryan lastname",
        roleName: "placeholder",
        tabs: {
          signHereTabs: [
            {
              anchorString: "/XSIGNHEREX/",
              anchorUnits: "pixels",
              anchorXOffset: "20",
              anchorYOffset: "10",
              tabLabel: "signHere",
            },
          ],
          textTabs: [
            {
              anchorString: "/XLEGALRENEWALPRICEX/",
              anchorUnits: "pixels",
              anchorXOffset: "20",
              anchorYOffset: "10",
              tabLabel: "renewalPrice",
              width: "100",
              value: renewalPrice,
            },
          ],
        },
      },
    ],
    status: "sent",
  };

  const config = {
    headers: {
      Authorization: `Bearer ${process.env.DOCUSIGN_ACCESS_TOKEN}`,
      "Content-Type": "application/json",
    },
  };

  try {
    const response = await axios.post(
      `${process.env.DOCUSIGN_BASE_URI}accounts/${process.env.DOCUSIGN_API_ACCOUNT_ID}/envelopes`,
      requestData,
      config
    );
    return response.data;
  } catch (error) {
    console.error("Error sending request:", error);
    throw error;
  }
};

const createRecipientView = async (
  envelopeId: string,
  accountId: string,
  returnUrl: string,
  userName: string,
  userEmail: string
): Promise<AxiosResponse> => {
  const requestData = {
    returnUrl,
    authenticationMethod: "None",
    email: userEmail,
    userName,
  };

  const config = {
    headers: {
      Authorization: `Bearer ${process.env.DOCUSIGN_ACCESS_TOKEN}`,
      "Content-Type": "application/json",
    },
  };

  try {
    const response = await axios.post(
      `${process.env.DOCUSIGN_BASE_URI}accounts/${accountId}/envelopes/${envelopeId}/views/recipient`,
      requestData,
      config
    );

    return response.data.url;
  } catch (error) {
    console.error("Error creating recipient view:", error);
    throw error;
  }
};

export async function POST(request: Request) {
  const { templateId, name, email, renewalPrice } = await request.json();
  try {
    const data = await createEnvelope(
      templateId,
      "[email protected]",
      "fullstackryan",
      convertPenniesToPounds(renewalPrice)
    );

    const viewUrl = await createRecipientView(
      data.envelopeId,
      `${process.env.DOCUSIGN_API_ACCOUNT_ID}`,
      "http://localhost:3000/",
      "fullstackryan", // what's username for and where does it come
      "[email protected]"
    );

    return NextResponse.json({
      recipientView: viewUrl,
      envelopeId: data.envelopeId,
    });
  } catch (error) {
    console.error("Failed to send the request:", error);
    return NextResponse.json({ error: "Failed to send the request" });
  }
}

enter image description here

Upvotes: 0

Views: 149

Answers (1)

Ry2254
Ry2254

Reputation: 1009

When sending the envelope I did not pass a "clientUserId". I have now added it to the request data. Also when creating the recipient view you must pass the same clientUserId. See the bottom code extract. The clientUserId is chosen by you and as long as it is the same one you pass to the creation of envelope and recipient view then you should be fine. For example you could use clientUserID: "1234"

  const requestData: TemplateRequest = {
    templateId,
    templateRoles: [
      {
        email: firmEmail,
        name: firmContactName,
        roleName: "signer",
        clientUserId,
        tabs: {
          signHereTabs: [
            {
              anchorString: "/XSIGNHEREX/",
              anchorUnits: "pixels",
              anchorXOffset: "20",
              anchorYOffset: "10",
              tabLabel: "signHere",
            },
          ],
          textTabs: [
            {
              anchorString: "/XLEGALRENEWALPRICEX/",
              anchorUnits: "pixels",
              anchorXOffset: "20",
              anchorYOffset: "10",
              tabLabel: "renewalPrice",
              width: "100",
              value: renewalPrice,
            },
          ],
        },
      },
    ],
    status: "sent",
  };

  const requestData = {
    returnUrl,
    authenticationMethod: "None",
    email: userEmail,
    userName,
    clientUserId,
  };

Upvotes: 1

Related Questions