Skip to main content

Hi,



I am currently using the Sign Request API to prefill a pre-created sign template with some data for a signer. Most of the time, my fields prefill completely as expected. (I’m passing them in prefill_tags => {document_tag_id: "tag_name", "text_value": "value" } format, and that seems to be working.)



However, every once in a while (maybe like one in every 4 sign requests?) my fields don’t populate correctly and are blank for the signer. I haven’t been able to identify any consistent similarities between these cases, and the success/failure cases have been with the exact same code and request pattern. Any thoughts on what might be going on here?

Hi @user147 , welcome to the forum.





It looks like the sign request goes through. I was thinking on the possibility of some data conversion error, (are all your tags of type text?) but I would expect some exception and that would prevent the sign request doesn’t go through.



Could it be a conversion error on your app side that silently sets the tags to empty?



Can you help us with an attempt to reproduce this?



Cheers


Hi @rbarbosa , appreciate the response. I’ll do my best to help reproduce! I won’t be able to offer specific code snippets, as it’s part of a closed source product.



What I can say after just trying to reproduce is that even in the case where the tag isn’t prefilled in the Sign UI, the 201 response I get back from the API’s body includes the prefill_tags info with the string I expect, i.e. this is included in the response is this:



"prefill_tags": l

{

"checkbox_value": null,

"date_value": null,

"document_tag_id": "my_tag_id",

"text_value": "value_passed"

}

]



So my strings seem to be making it over from my app successfully. I’m not sure if the date_value and checkbox_value fields should be included, but they’re empty so that follows what I’d expect to receive back too.




That is fine, I’ll work with what you can give us.



This is interesting, it seems the value of the tags actually end up on the sign request.



Would it be possible that the sign request has more than one signer and there are tags with duplicate id’s?



What I mean is could there be a miss match or duplication in the tag id’s versus the signer id?



For example, consider this tag: agt|1|id:tag_full_name|n:enter your complete name]], where t stands for text and 1 is for the first signer. If I have a e t|2|id:tag_full_name|n:enter your complete name]] then the tag id tag_full_name could cause confusion, even if pointing to signer 2.



For clarification, are you using a document (word/pdf) with tags as the example above or are you using a sign template created inside the box app?



A tagged document looks like this:





A template created in the box app looks like this:





Let us know.



Cheers


I’m using a template created in the Box app. I do have multiple signers, however they have different ids and the order does match what I’m sending in the request. I also only have one field that has the tag ID I’m targeting, which is designated for my first signer.


Hi @rbarbosa , just following up to see if there’s been any movement or more info uncovered here, as this would really enhance a feature we’re currently working on and hoping to ship soon. Thanks for the help!


Hi @user147 ,



This is not forgotten.



I’m setting up a test with a template and then generate 10 or so requests and see if I get the same symptoms.



On your side are some of the request fields still coming out empty?



I’ll keep you posted.


Awesome, really appreciate the update. Behavior is still the same on my end, fields are sometimes filled and sometimes not with the same input and output as far as the API is concerned.



Thanks again.


Hi @user147



I wasn’t able to replicate this…



I’ve created 10 signature request with the following result:



Simple sign request: f025d707-42a9-4b0e-bc3a-bed548e979a6

Status: sent

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+0@gmail.com



Simple sign request: 7917303c-b6b7-463d-8fcd-b11c91e31d52

Status: sent

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+1@gmail.com



Simple sign request: 31b868b1-5646-44fd-826e-60712db78535

Status: created

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+2@gmail.com



Simple sign request: 3f9e5131-67a2-4c43-a93b-51677ec8a909

Status: created

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+3@gmail.com



Simple sign request: 0d60e646-db23-4fc2-83a0-565302e3eb6d

Status: sent

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+4@gmail.com



Simple sign request: b09b01b5-a7fe-455f-82ed-19aa456db908

Status: sent

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+5@gmail.com



Simple sign request: fb4a05e7-bf68-4684-ad9e-9697fe76da5c

Status: sent

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+6@gmail.com



Simple sign request: f3556afe-829a-40bf-a2a2-287d8bdeb1fe

Status: sent

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+7@gmail.com



Simple sign request: fe49835f-0ab6-40a2-88ff-60d1ff43b17e

Status: created

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+8@gmail.com



Simple sign request: c2242ce6-b3d5-40ee-9069-01d2d15aa22f

Status: created

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+9@gmail.com



Notice, some of the status are sent, and some were created, this is an asynchronous process so it may take some time to actually send all the requests.



After getting the email, and signing each one of them, I listed the details from the user requests using this script:



def check_sign_request_by_id(client: Client, sign_request_id: str):

"""Check sign request by id"""

sign_request = client.sign_requests.get_sign_request_by_id(sign_request_id)



print(f"\nSimple sign request: {sign_request.id}")

print(f" Status: {sign_request.status.value}")



print(f" Signers: {len(sign_request.signers)}")

for signer in sign_request.signers:

print(f" {signer.role.value}: {signer.email}")

for input in signer.inputs:

content_type = input.content_type

value = None



if content_type == SignRequestSignerInputContentTypeField.CHECKBOX:

value = input.checkbox_value

elif content_type == SignRequestSignerInputContentTypeField.TEXT:

value = input.text_value

elif (

content_type

== SignRequestSignerInputContentTypeField.FULL_NAME

):

value = input.text_value

elif content_type == SignRequestSignerInputContentTypeField.DATE:

value = input.date_value



print(

f" {input.type.value}: {value if value is not None else '<other>'}"

)



and in the main script:



    # list sign requests

user_sign_requests = client.sign_requests.get_sign_requests()

print(f"\nSign requests: {len(user_sign_requests.entries)}")

for sign_request in user_sign_requests.entries:

check_sign_request_by_id(client, sign_request.id)



Resulting in:



Sign requests: 10



Simple sign request: c2242ce6-b3d5-40ee-9069-01d2d15aa22f

Status: signed

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+9@gmail.com

date: 2023-12-08

text: jjjj

signature: <other>



Simple sign request: fe49835f-0ab6-40a2-88ff-60d1ff43b17e

Status: signed

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+8@gmail.com

date: 2023-12-08

text: iii

signature: <other>



Simple sign request: f3556afe-829a-40bf-a2a2-287d8bdeb1fe

Status: signed

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+7@gmail.com

date: 2023-12-08

text: hhh

signature: <other>



Simple sign request: fb4a05e7-bf68-4684-ad9e-9697fe76da5c

Status: signed

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+6@gmail.com

text: ggg

signature: <other>

date: 2023-12-08



Simple sign request: b09b01b5-a7fe-455f-82ed-19aa456db908

Status: signed

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+5@gmail.com

signature: <other>

text: fff

date: 2023-12-08



Simple sign request: 0d60e646-db23-4fc2-83a0-565302e3eb6d

Status: signed

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+4@gmail.com

date: 2023-12-08

text: eee

signature: <other>



Simple sign request: 3f9e5131-67a2-4c43-a93b-51677ec8a909

Status: signed

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+3@gmail.com

date: 2023-12-08

text: ddd

signature: <other>



Simple sign request: 31b868b1-5646-44fd-826e-60712db78535

Status: signed

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+2@gmail.com

text: ccc

date: 2023-12-08

signature: <other>



Simple sign request: 7917303c-b6b7-463d-8fcd-b11c91e31d52

Status: signed

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+1@gmail.com

signature: <other>

text: bbb

date: 2023-12-08



Simple sign request: f025d707-42a9-4b0e-bc3a-bed548e979a6

Status: signed

Signers: 2

final_copy_reader: ...@gmail.com

signer: ...+0@gmail.com

date: 2023-12-08

signature: <other>

text: aaa



Notice that all status are sent, meaning the sign request is complete and without errors, and I can access the input data.



So what could possibly be wrong?



Each input has a type and stores the value in different properties. For example an input type of full_name stores the data under input.text_value, however an input type of date, stored the data under input.date_value.


Could there be a miss match between the input types and where your app is getting the values from?



The other option, but I haven’t been able to replicate, is that the sign request is not finished yet or has an error. Have your app check for the signed state before getting the values.



I’m running out of options here, so if this doesn’t yield any results on your side, my recommendation is to open a support ticket.



Finally I’ve created this sample script using the Gen Python SDK, and a modified sign workshop script (see below).



import logging



from utils.box_client_oauth import ConfigOAuth, get_client_oauth

from box_sdk_gen.client import BoxClient as Client

from box_sdk_gen.schemas import (

SignRequest,

SignRequestCreateSigner,

SignRequestSignerInputContentTypeField,

FolderBaseTypeField,

FolderMini,

)



# from utils.oauth_callback import open_browser



logging.basicConfig(level=logging.INFO)

logging.getLogger("box_sdk_gen").setLevel(logging.CRITICAL)



SIGN_DOCS_FOLDER = "234102987614"



SIMPLE_PDF = "1355143830404"

SIMPLE_DOC = "1358077513913"

CONTRACT = "1358047520478"



SIGNER_A = "YOUR_EMAIL+A@gmail.com"

SIGNER_A_PHONE = "+15554443322"



SIGNER_B = "YOUR_EMAIL+B@gmail.com"



APPROVER = "YOUR_EMAIL+APPROVER@gmail.com"

FINAL_COPY = "YOUR_EMAIL+FINAL_COPY@gmail.com"



TEMPLATE_SIMPLE = "94e3815b-f7f5-4c2c-8a26-e9ba5c486031"





def create_sign_request(client: Client, template_id: str, signer_email: str):

"""Create sign request from template"""

parent_folder = FolderMini(

id=SIGN_DOCS_FOLDER, type=FolderBaseTypeField.FOLDER

)



signer = SignRequestCreateSigner(

email=signer_email,

)



sign_request = client.sign_requests.create_sign_request(

signers= signer],

parent_folder=parent_folder,

template_id=template_id,

)



return sign_request





def check_sign_request_by_id(client: Client, sign_request_id: str):

"""Check sign request by id"""

sign_request = client.sign_requests.get_sign_request_by_id(sign_request_id)



print(f"\nSimple sign request: {sign_request.id}")

print(f" Status: {sign_request.status.value}")



print(f" Signers: {len(sign_request.signers)}")

for signer in sign_request.signers:

print(f" {signer.role.value}: {signer.email}")

for input in signer.inputs:

content_type = input.content_type

value = None



if content_type == SignRequestSignerInputContentTypeField.CHECKBOX:

value = input.checkbox_value

elif content_type == SignRequestSignerInputContentTypeField.TEXT:

value = input.text_value

elif (

content_type

== SignRequestSignerInputContentTypeField.FULL_NAME

):

value = input.text_value

elif content_type == SignRequestSignerInputContentTypeField.DATE:

value = input.date_value



print(

f" {input.type.value}: {value if value is not None else '<other>'}"

)





def main():

"""Simple script to demonstrate how to use the Box SDK"""

conf = ConfigOAuth()

client = get_client_oauth(conf)



user = client.users.get_user_me()

print(f"\nHello, I'm {user.name} ({user.login}) {{user.id}]")



# # create 10 sign request from template



# for i in range(10):

# sign_request = create_sign_request(

# client, TEMPLATE_SIMPLE, "your_email+" + str(i) + "@gmail.com"

# )

# check_sign_request_by_id(client, sign_request.id)



# list sign requests

user_sign_requests = client.sign_requests.get_sign_requests()

print(f"\nSign requests: {len(user_sign_requests.entries)}")

for sign_request in user_sign_requests.entries:

check_sign_request_by_id(client, sign_request.id)





if __name__ == "__main__":

main()





Let us know if this helps



Cheers


Reply