# Creating a user consent application using the Node SDK ## Creating the application It's time to get the code for your application. Copy and paste the code from the right panel into `index.js`. We'll step through the code below. ### Initialization Review the following code: ```javascript const { SinchClient, SmsRegion } = require("@sinch/sdk-core"); const fastify = require("fastify")(); const portAddr = 3000; const sinchClient = new SinchClient({ projectId: "YOUR_project_id", keyId: "YOUR_access_key", keySecret: "YOUR_access_secret", region: "us/eu", }); let group; let autoReply; ``` This code sets up everything your application needs to function. First the Sinch SDK and Fastify web server are imported and a port number is initialized. Then an SDK client is created and initialized with your credentials. To start using the SDK, you need to initialize the main client class with your credentials from your Sinch [dashboard](https://dashboard.sinch.com/dashboard). ```javascript const {SinchClient} = require('@sinch/sdk-core'); const sinchClient = new SinchClient({ projectId: "YOUR_project_id", keyId: "YOUR_access_key", keySecret: "YOUR_access_secret" }); ``` Note For testing purposes on your local environment it's fine to use hardcoded values, but before deploying to production we strongly recommend using environment variables to store the credentials, as in the following example: **`.env` File** ```shell PROJECTID="YOUR_project_id" ACCESSKEY="YOUR_access_key" ACCESSSECRET="YOUR_access_secret" ``` **`app.js` File** ```javascript const {SinchClient} = require('@sinch/sdk-core'); const sinchClient = new SinchClient({ projectId: process.env.PROJECTID, keyId: process.env.ACCESSKEY, keySecret: process.env.ACCESSSECRET }); ``` The `region` parameter has been included in this tutorial but it can be omitted, in which case the SDK will default to the US region. Finally a couple of variables are declared, which will store key information for your application to do its job. ### Receiving incoming messages Now we'll review the code that allows your app to recieve incoming messages: ```javascript fastify.post("/", async (request, reply) => { let message = request.body; let groupMembers = await sinchClient.sms.groups.listMembers({ group_id: group.id, }); if (message.body === "SUBSCRIBE" && !groupMembers.includes(message.from)) { await sinchClient.sms.groups.update({ group_id: group.id, updateGroupRequestBody: { add: [message.from] }, }); autoReply = "Congratulations! You are now subscribed to " + group.name + ". Text STOP to leave this group."; } else if (message.body === "STOP" && groupMembers.includes(message.from)) { await sinchClient.sms.groups.update({ group_id: group.id, updateGroupRequestBody: { remove: [message.from] }, }); autoReply = "We're sorry to see you go. You can always rejoin " + group.name + ' by texting SUBSCRIBE to ' + message.to; } else { autoReply = 'Thanks for your interest. If you want to subscribe to this group, text SUBSCRIBE to ' + message.to; } }); ``` This is similar to the application in the [Receive an SMS Message](/docs/sms/getting-started/node-sdk/handle-incoming/) guide. Its basic job is to listen for an inbound message and respond with an action. However, where the *Receive Message* app simply returned a reply containing the inbound message, this application contains relatively complex business logic to handle incoming requests appropriately. Note: While we need to create and delete a group for this demonstrative tutorial, it's worth noting that in production, recipients would probably be subscribing to, or unsubscribing from, a prexisting group. The logic is designed to cover the following basic contingencies: - If a user is *not* already a group member and wants to join, the app looks for the **SUBSCRIBE** keyword. It then uses the SDK `update` method to add them to the group and assigns a confirmation message to the variable `autoReply`. - When a user *is* already a group member and wants to leave, the app looks for the **STOP** keyword. It then uses the SDK `update` method to remove them from the group and assigns a confirmation message to the variable `autoReply`. - If a user is not a group member but doesn't know the keyword to join, the application sends a message thanking them and telling them the right keyword. The final code is for sending the confirmation messages assigned to `autoReply`: ```javascript let response = await sinchClient.sms.batches.send({ sendSMSRequestBody: { to: [message.from], from: message.to, body: autoReply, }, }); console.log(JSON.stringify(response)); reply.type("application/json").code(200); ``` ### Starting the server Now let's review the `startServer` function beneath `fastify.post`. It creates the group and starts the server. ```javascript async function startServer() { group = await sinchClient.sms.groups.create({ createGroupRequestBody: { name: "Sinch Pirates" }, }); fastify.listen({ port: portAddr }, () => { console.log(`Listening at http://localhost:${portAddr}`); }); } ``` Fastify's `listen` method starts the server on the port number specified by `portAddr`. In this tutorial, `startServer` creates the group as well as starting the server. This is done for convenience, but in a real application, it would be much more efficacious to use a preexisting group. That way, you don't have to make a new one every time you start the app! We don't want our Sinch Pirates group hanging around in the database. This callback will ensure our group is deleted as soon as we hit Ctrl+C: ```javascript process.on("SIGINT", async (res, err) => { console.log(group.id); await sinchClient.sms.groups.delete({ group_id: group.id, }); console.log(res); fastify.close(); }); ``` Let's finish by adding a call to the `startServer` function: ```javascript startServer(); ``` This will be the first function called when we start our Node application.