freshbooks / freshbooks-nodejs-sdk

Node.js SDK for the FreshBooks API
MIT License
8 stars 12 forks source link

Client.projects.create does not work #256

Closed pniv closed 2 years ago

pniv commented 2 years ago

Here is the code that I run in RunKit

const client = new api.Client(clientId, {
    accessToken: token,
});

const project = {
   "title": "Test Project"
 };

const { projects } = await client.projects.list(businessId)
console.log(`Projects`, data)           // This works!

const { data } = await client.projects.create(project, businessId)
console.log(`Created project`, data)

The client is setup correctly and I can read the projects data. The problem is that I cannot create new project.

I suspect that the problem is in the Freshbooks API itself: https://www.freshbooks.com/api/project I can successfully invoke APIs for projects using Postman. But when I try to create one, I receive the following error:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">

500 Internal Server Error

Internal Server Error

The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.

pniv commented 2 years ago

My token is has correct scopes (user:project:read and user.project.create), because I can edit existing project.

amcintosh commented 2 years ago

Hi! Thanks for reaching out.

The above call:

const project = {
   "title": "Test Project"
 };

const { data } = await client.projects.create(project, businessId)
console.log(`Created project`, data)

Worked for me.

Looking at the logs for the past few hours I see a number of 500 failures due to an empty request payloads. Could you perhaps be sending an empty project payload? Alternatively, there could perhaps be an issue with your account if it is also failing when you use postman. Could you reach out to our API support team with your issue (newapi@freshbooks.com)?

Clearly, even if that is the case, a 500 server error is not the appropriate response from our API, so we should address that as well.

pniv commented 2 years ago

Thank you, @amcintosh! I tried many times with Postman and with the SDK, but it always fails with status code 500. Maybe there is a problem with the account. I will reach out the API support team.

Thanks!

calvin-fb commented 2 years ago

Try sending:

const project = {
  "project": {
    "title": "Test Project"
  }
 }

Instead of:

const project = {
  "title": "Test Project"
}
pniv commented 2 years ago

I don't think this is correct. There is a code in the SDK that does this before sending the request:

// In APIClient.js
        this.projects = {
           ....
            create: (project, businessId) => this.call('POST', `/projects/business/${businessId}/project`, {
                transformResponse: Project_1.transformProjectResponse,
                transformRequest: Project_1.transformProjectRequest,
            }, project, 'Create Project'),

// In Project.js
/**
 * Converts @Project object into JSON string
 *
 * @param project @Project object
 * @returns JSON string representing Project request
 */
function transformProjectRequest(project) {
    const model = {
        project: {
            id: project.id,
            title: project.title,
            description: project.description,
            due_date: project.dueDate,
            client_id: project.clientId,
            internal: project.internal,
            budget: project.budget,
            fixed_price: project.fixedPrice,
            rate: project.rate,
            billing_method: project.billingMethod,
            project_type: project.projectType,
            project_manager_id: project.projectManagerId,
            active: project.active,
            complete: project.complete,
            sample: project.sample,
            logged_duration: project.loggedDuration,
            billed_amount: project.billedAmount,
            billed_status: project.billedStatus,
            retainer_id: project.retainerId,
            expense_markup: project.expenseMarkup,
        },
    };
    return JSON.stringify(model);
}
pniv commented 2 years ago

Try sending:

const project = {
  "project": {
    "title": "Test Project"
  }
 }

This is what I am sending using Postman: Screenshot 2022-03-13 at 15 33 10

amcintosh commented 2 years ago

Interesting. I see a recent 403 exception that seems to be swallowed and thrown as a 500.

Does the identity you've authenticated your application with have permissions to create projects? While the application may have the correct scopes, if the authorizing user doesn't have that permission, then the application will not have that permission.

Again, if this is the case, we should be presenting the 403, not the 500, but this could be the cause.

pniv commented 2 years ago

When I am logged in which the same user I can manually create/edit/delete projects. What information do you need to be able to identify the request? Account id? Business id?

amcintosh commented 2 years ago

@pniv I've confirmed that we have a permissions issue on our end, so this is not an issue with your account. I am working to resolve the issue.

pniv commented 2 years ago

Thank you, @amcintosh ! Please let me know if I can help with anything.

amcintosh commented 2 years ago

@pniv The change has been deployed. I believe it should resolve your issue. If not, please let us know.

pniv commented 2 years ago

@amcintosh Create project works! Thank you so much!

Edit project still fails with error 500.

When doing edit, should I send the entire project object? Or just the modified fields? I am sending just "title" and "client_id". Maybe it is my error in this case...

amcintosh commented 2 years ago

Hi! I suspect that this is another issue on our end, but I'll have to ask around.

amcintosh commented 2 years ago

HI @pniv. I believe the project edit should be working now.

pniv commented 2 years ago

Yes, it is working!

amcintosh commented 2 years ago

Excellent!