Custom envelope fields using Docusign REST API - ruby-on-rails

I'm using the docusign_rest gem to integrate with the Docusign REST API in my rails application. I have created a custom envelope field in the Docusign admin called SFID. I need to pass an ID into SFID inside of the envelope. I'm getting the following error with my JSON code:
{"errorCode"=>"INVALID_REQUEST_BODY", "message"=>"The request body is missing or improperly formatted. Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'API_REST.Models.v2.customFields' because the type requires a JSON object (e.g. {\"name\":\"value\"}) to deserialize correctly.\r\nTo fix this error either change the JSON to a JSON object (e.g. {\"name\":\"value\"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.\r\nPath 'customFields', line 1, position 1073."}
My controller code:
#envelope_response = client.create_envelope_from_template(
status: 'sent',
email: {
subject: "The test email subject envelope",
body: ""
},
template_id: '90B58E8F-xxxxx',
custom_fields: [
{
textCustomFields: [
{
name: 'SFID',
value:'12345',
required: 'false',
show: 'true'
}
]
}
],
signers: [
...
The Docusign API explorer says the following is the correct way to push an envelope custom field:
{
"customFields": {
"textCustomFields": [
{
"value": "0101010101",
"required": "true",
"show": "true",
"name": "SFID"
},
{
"required": "true",
"show": "true"
}
]
}
}
The Docusign_rest gem says the following on custom envelope fields:
customFields - (Optional) A hash of listCustomFields and textCustomFields.
# Each contains an array of corresponding customField hashes.
# For details, please see: http://bit.ly/1FnmRJx
What formatting changes to I need to make to my controller code to get it to successfully push a custom envelope field?

You have an extra array in your customFields node.
Remove the [] array from your custom_fields:
#envelope_response = client.create_envelope_from_template(
status: 'sent',
email: {
subject: "The test email subject envelope",
body: ""
},
template_id: '90B58E8F-xxxxx',
custom_fields:
{
textCustomFields: [
{
name: 'SFID',
value:'12345',
required: 'false',
show: 'true'
}
]
},
signers: [
...
Also I'm assuming that your client.create_envelope_from_template is converting your _'s into a camelCased string. if that is not happening, then that also needs to change.

Related

Is parent definition in API request body required if it's partial sub child properties are marked required?

Suppose I have the following OpenAPI definition (ignore the indentation or missing attributes):
FooData:
type: object
additionalProperties: false
description: Holds the foo data Information.
required:
- id
- contact
properties:
id:
description: Identifier
type: string
maxLength: 255
minLength: 1
pattern: ^[a-zA-Z0-9\-]{1,255}$
identity:
description: Holds customer identity info.
$ref: '#/MyIdentity' ....
MyIdentity:
type: object
additionalProperties: false
description: Holds the customer identity information.
required:
- userId
properties:
userId:
type: integer
format: int64
minimum: 0
maximum: 9223372036854775807
description: Unique Identification Number which is specific to individual user.
firstName:
type: string
description: user's First name.
maxLength: 32
minLength: 1
pattern: ^[a-zA-Z\s]{1,32}$ ....
As you see, MyIdentity is not required in FooData however its property userID is marked as required.
Can we ignore the full MyIdentity object in the request body while hitting the API?
Assuming the request body schema is FooData:
Can we ignore the full MyIdentity object in the request body while hitting the API?
Yes - because the FooData.identity property is not required so it can be omitted. However, if the FooData.identity property is present, it must be an object and contain at least the userId property.
In other words, the following FooData payloads are valid:
{
"id": "abc",
"contact": "..."
}
{
"id": "abc",
"contact": "...",
"identity": {
"userId": 12345
}
}
but these payloads are invalid:
// No `userId` in `identity`
{
"id": "abc",
...,
"identity": {}
}
// No `userId` in `identity`
{
"id": "abc",
...,
"identity": {
"firstName": "Alex"
}
}
// `identity` is not an object
{
"id": "abc",
...,
"identity": null
}
// `identity` is not an object
{
"id": "abc",
...,
"identity": "blah"
}

Taking input as array in swagger not working

I have the following code for my swagger documentation. Here I am trying to create an API where I want to take input as an array of objects. so far I am doing like following.
{
method: 'POST',
path: '/api/Route',
handler: function(request, reply) {
//some operations
reply('Success');
},
config: {
description: 'Create a Route',
tags: ['api', 'user'],
auth: 'UserAuth',
validate: {
payload: {
"array": [{
userId: Joi.string().trim().required(),
status: Joi.number().required()
},
{
userId: Joi.string().trim().required(),
status: Joi.number().required()
},
{
userId: Joi.string().trim().required(),
status: Joi.number().required()
}
]
}
},
plugins: {
'hapi-swagger': {
responseMessages: swaggerDefaultResponseMessages
}
}
}
}
so what actually going on when I run the above code the swagger creates the documentation like this.
this is a link to the image. so please can anybody tell me why I am not getting the whole array in swagger documentation instead getting only one element of the array. and I also saw the Following question but unable to understand in which file they are making these changes. Could anybody help? Thanks in advance.
You could use the array validation of Joi. Then in the input, you could just pass the array into it. for that, you just need to write the following code in your payload instead of what you are writing at present.
payload: {
userData: Joi.array().items({
userName: Joi.string(),
status: Joi.string()
})
}
after that you swagger documentation looks something like this.
userData is your array of objects. and you could give input array of objects as following.
"userData": [{
"userName": "string", // objects
"status": "string"
},
{
"userName": "string", // objects this way you can add more
"status": "string"
}
]

JIRA API after POST returns { errorMessages: [ 'Internal server error' ], errors: {} }

I am trying to create a new issue utilizing the JIRA REST API and whenever I try, I get back the following generic error:
{ errorMessages: [ 'Internal server error' ], errors: {} }
I can successfully GET from the API, and the credentials I'm connecting with have full Admin access to JIRA (so it's not an Auth issue), but I get this error every time with POST. Below is a snippet of the JSON data I'm sending. Am I missing anything obvious?
Below is my JavaScript code. Note I'm using jira-connector from npm. (Real domain replaced with mydomain for this sample code)
const JiraClient = require('jira-connector');
const dotenv = require('dotenv').config();
function createNewIssue(fields) {
const encoded = process.env.JIRA_ENCODED_PW;
const jira = new JiraClient({
host: 'mydomain.atlassian.net',
basic_auth: {
base64: encoded
}
});
return new Promise((resolve, reject) => {
jira.issue.createIssue(fields, (error, issue) => {
if (error) {
console.log(error);
reject(error);
} else {
console.log(issue);
resolve(encoded);
}
});
})
}
Below is the JSON that's being passed into fields in the JS above. Note customfield_17300 is a radio button, and customfield_17300 is a multi-select box. For both cases, I've tried using the "id" and also the actual string "name" value. All IDs below were taken straight from a API GET of the same issue in question:
{
"fields": {
"project": {
"id": "13400"
},
"summary": "TEST API TICKET - 01",
"issuetype": {
"id": "11701"
},
"customfield_14804": { "id": "13716" },
"customfield_14607": "Hardware",
"customfield_17300": [
{
"id": "18322"
}
] ,
"customfield_16301": "Customer PO",
"customfield_14800": "LA, California",
"customfield_16302": "FEDEX 234982347g"
}
}
sigh I figured it out... other posts that said this cryptic error was due to a malformed JSON were correct.
In my route, I passed fields as coming from req.body.fields which actually dove into the fields values instead of passing it straight through. This made it so that when the JSON was sent to JIRA the fields outer wrapper was missing. I changed my route to pass along req.body instead of req.body.fields and all was well.
...that was a fun 4 hours...

How do you define an array of different examples in a Swagger spec?

I'm trying to document an API with a static swagger file that can return some JSON that contains an array that looks something like this:
[
{
"type": "type A",
"field A": "this field is specific to type A"
},
{
"type": "type B",
"field B": "this field is specific to type B"
}
]
I've tried a few different ways of defining my spec using either polymorphism or explicitly defining multiple examples. The examples have always either ended up looking like:
[
{
"type": "type A",
"field A": "this field is specific to type A",
"field B": "this field is specific to type B"
}
]
or just:
[
{
"type": "type A",
"field A": "this field is specific to type A"
}
]
Is there a way to define an example in my swagger spec so that the example payload shown by swagger-ui will contain an array containing an example of Type A and an example of Type B like the first JSON I wrote?
Actually, you can. In the responses object, put an examples object with an array as the value of the mime type. like so:
400:
description: Bad Request
examples:
application/json:
[
{
code:10000,
message:"Missing Input Parameters",
fieldA: "AAAAA"
},{
code:42,
message:"Ask the question",
fieldB: "BBBBBB"
}
]
default:
description: Unexpected error
schema:
$ref: '#/definitions/Error'
You can't.
You can only define one example per mime-type per response :
{
"description": "A response",
"schema": {
"type": "string"
}
},
"examples": {
"application/json": {
"name": "Dog"
},
"application/xml": {
"name": "Cat"
}
}
}
If you want add complete scenario, I suggest you to write (or generate) a full scenario example in an HTML page and link it with an externalDocs. You can define externalDocs in root, operations, tags and schemas.

Parsing JSON hash with each generates "can't convert String into Integer"

I am parsing JSON from an API with the following code:
def json_test
content = open("API URL").read
json = JSON.parse(content)
json.each do |a|
puts a["first_name"]
end
end
The reason I'm using each is because the API request will return an array of hashes for multiple users, like this:
[{
"id": "1",
"first_name": "John"
},
{
"id": "2",
"first_name": "Bob"
}]
However, the API will return just a hash if the request only returns a single user, like thus:
{
"id": "2",
"first_name": "Bob"
}
This is where I'm getting the error message: can't convert String into Integer (TypeError)
I've been searching for a good way to be able to parse when it's not returning an array but just a hash and I'm stumped. Any pointers?
Array.wrap is designed just for this purpose.
Wraps its argument in an array unless it is already an array (or array-like).
Array.wrap({ a: 1 }) # => [{ a: 1 }]
Array.wrap [{ a: 1 }, { b: 2 }] # => [{ a: 1 }, { b: 2 }]
One way is putting it all inside a single element array and flattening it:
json = [JSON.parse(content)].flatten
If it is not an array, the flatten will be noop. If it is, the extra array layer will be removed.

Resources