Close service jobs
Learn how to set fulfillment data and set a job as complete.
Learn how to set fulfillment data, such as:
- Start and end date-times
- Fulfillment resources
- Fulfillment documents such as Proof Of Appointment (POA) files
- Job status, such as completed or cancelled
To set a job as complete, use the following operations:
setAppointmentFulfillmentDatasets data such as fulfillment date-times, resources, and fulfillment document identifiers.createServiceDocumentUploadDestinationcreates an upload destination for fulfillment documents such as Proof Of Appointment (POA) files.completeServiceJobByServiceJobIdsets a service job as completed.cancelServiceJobByServiceJobIdsets a service job as cancelled.
Before you set a job as complete, you must provide appointment fulfillment data, using setAppointmentFulfillmentData and createServiceDocumentUploadDestination. There are four types of fulfillment data:
- Estimated Arrival Time: The range of time when the technician is expected to arrive at the fulfillment location.
- Appointment Fulfillment Times: The actual fulfillment date-time start and end.
- Appointment Fulfillment Resources: The actual resources that fulfilled an appointment.
- Appointment Fulfillment Documents: Documents that:
- Serve as evidence of service completion
- Were used in the course of fulfillment
- Record aspects of fulfillment
Note
The Amazon business line and service sellers determine the minimum requirements for fulfillment data and documents to close a job. Service sellers should confer with their relevant Amazon business line partners to settle appropriate API usage before they integrate with the Services API.
Prerequisites
To complete this tutorial, you need:
- Authorization from the seller for whom you are making calls. Refer to Authorizing Selling Partner Applications for more information.
- A service job identifier assigned to the service provider. Only jobs assigned to the service provider can be accessed. Job status are verified as in
NotServicedstate. - A scheduled appointment identifier pre-configured in Amazon Systems for the service provider.
- An active appointment.
Step 1. Set or update service appointment fulfillment data
The setAppointmentFulfillmentData operation updates multiple aspects of service job appointment fulfillment data that you must record before you set a job as complete.
Step 2. Upload a fulfillment document
The createServiceDocumentUploadDestination operation creates a storage destination and identifier for a fulfillment document. This document is necessary to set a job as complete.
To upload a document:
- Create an upload destination for the service document with the
createServiceDocumentUploadDestinationoperation. - Encrypt and upload the file.
Use the information the response provides to encrypt and upload the file.
The following Java sample encrypts and uploads a feed. This sample code uses the Apache HTTP client.
- Use the following as input for the sample code:
a. Your file content as the argument for the stream parameter of theInputStreammethod of theUploadToDestinationExampleclass.
b. TheinitializationVectorandkeyvalues from thecreateServiceDocumentUploadDestinationresponse as arguments for theivandkeyparameters of theEncryptionDetailsmethod of theEncryptionDetailsclass.
c. Theurlvalue from thecreateServiceDocumentUploadDestinationresponse as the argument for theurlparameter of theuploadToDestinationmethod of theUploadToDestinationExampleclass. - Save the
sha256sumvalue to pass as theContentSha256parameter insetAppointmentFulfillmentData.
package com.amazon.spapi;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.HttpClients;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.InputStream;
import java.security.DigestInputStream;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
public class UploadToDestinationExample {
static final String SHA_256 = "SHA-256";
static final String AES = "AES";
static final int AES_BLOCK_SIZE = 16;
static final Base64.Encoder BASE64_ENCODER = Base64.getEncoder();
static final Base64.Decoder BASE64_DECODER = Base64.getDecoder();
static final CryptoProvider AES_CRYPTO_PROVIDER = UploadToDestinationExample::getInitializedCipher;
static InputStream buildCipherInputStream(EncryptionDetails encryptionDetails, InputStream stream, int mode) {
return new CipherInputStream(stream,
AES_CRYPTO_PROVIDER.getInitializedCipher(mode, encryptionDetails));
}
private static InputStream buildCipherInputStream(EncryptionDetails encryptionDetails, InputStream stream) {
return buildCipherInputStream(encryptionDetails, stream, Cipher.ENCRYPT_MODE);
}
static Cipher getInitializedCipher(int mode, EncryptionDetails details) {
Cipher cipher;
try {
cipher = Cipher.getInstance(AES);
Key key = new SecretKeySpec(BASE64_DECODER.decode(details.getKey()), AES);
byte[] iv = BASE64_DECODER.decode(details.getIv());
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(mode, key, ivParameterSpec, new SecureRandom());
} catch (GeneralSecurityException e) {
throw new IllegalStateException("Could not create Cipher for key-iv pair", e);
}
return cipher;
}
UploadDetails uploadToDestination(EncryptionDetails encryptionDetails, String uploadDestinationId, String url,
String contentType,
long documentLength,
InputStream inputStream) {
try {
inputStream = buildCipherInputStream(encryptionDetails, inputStream);
DigestInputStream sha256sumStream = new DigestInputStream(inputStream, MessageDigest.getInstance(SHA_256));
inputStream = sha256sumStream;
// Put the file
HttpClient httpClient = HttpClients.createDefault();
HttpPut httpPut = new HttpPut(url);
// This content length calculation is specific to AES
long contentLength = (documentLength / AES_BLOCK_SIZE + 1) *
AES_BLOCK_SIZE;
// This sets the Content-Length header since we specified the contentLength
HttpEntity document = new InputStreamEntity(inputStream,
contentLength);
httpPut.setHeader("Content-Type", contentType);
httpPut.setEntity(document);
//Put the content in the S3 Pre-signed URL
HttpResponse httpResponse = httpClient.execute(httpPut);
if (httpResponse == null ||
(httpResponse.getStatusLine().getStatusCode() / 100) != 2) {
// Handle error responses here.
throw new IllegalStateException("Could not upload to S3.");
}
// Document was successfully uploaded!
byte[] sha256sumDigest = sha256sumStream.getMessageDigest().digest();
String sha256sum = BASE64_ENCODER.encodeToString(sha256sumDigest);
return new UploadDetails(uploadDestinationId, sha256sum);
} catch (IOException | NoSuchAlgorithmException e) {
throw new RuntimeException("Error occurred when attempting to encrypt or upload to S3.", e);
} finally {
IOUtils.closeQuietly(inputStream);
}
}
}
Step 3. Complete a service job
The completeServiceJobByServiceJobId operation marks a service job as complete. If the given job is the only active job in the order, then it marks the entire order as complete.
Step 4. Cancel a service job
The cancelServiceJobByServiceJobId operation marks a service job as cancelled. If the given job is the only active job in the order, then it marks the entire order as cancelled.
Cancellation reason codes by marketplace
| Reason code | Reason description | Default | Heavy bulk |
|---|---|---|---|
| S1 | Customer didn't show up. | US, IN, UK, DE | US, IN, UK, DE |
| S2 | Customer outside service area. | - | DE |
| S3 | Work is different than scoped and order cannot be completed. | US, IN, UK, DE | US, IN, UK, DE |
| S4 | Provider unable to contact customer. | - | DE |
| S5 | Provider cannot meet customer's schedule. | - | DE |
| S6 | Job requires professional trade license. | - | DE |
| S7 - S12 | Codes not in use. | - | - |
| S13 | Provider cannot meet original appointment. | US, IN, UK, DE | US, IN, UK |
| S14 | Provider cannot meet new appointment request. | US | US |
| S15 | Problem with Amazon product or its delivery. | US, IN, UK, DE | US, IN, UK |
| S16 | Problem with non-Amazon product, delivery, or service. | US, UK, DE | US, UK |
| S17 | I don't need this service. | US, IN | US, IN |
| S18 - S19 | Codes not in use. | - | - |
| S20 | Too expensive. | IN | IN |
| S21 - S26 | Codes not in use. | - | - |
| S27 | Brand installed. | IN | IN |
| S28 | Coverage area changed. | - | - |
| S29 | Pricing mistake. | - | - |
| S30 | No longer works with customer schedule. | - | - |
| S31 | Product damaged. | IN | - |
| S32 | Risky site. | IN | - |
| S33 | Customer wants cancellation. | IN | - |
| S34 | Site not ready. | IN | - |
| S35 | Product not delivered. | IN | - |
| S36 | Additional material needed. | IN | - |
| S37 | Customer wants reschedule. | IN | - |
| S38 | Product returned. | IN | - |
| S39 | We could not reach you. | IN | - |
| S40 | Service already completed. | IN | - |
| S41 | Service in another location. | IN | - |
| S42 | Needs revisit. | IN | - |
| S43 | Documents not available. | IN | - |
| S44 | Slot missed. | IN | - |
| S45 | Parts not available. | IN | - |
| S46 | Wrong completion. | IN | - |
| S47 | Need customer approval for repair. | IN | - |
| S48 - S50 | Codes not in use. | - | - |
| S51 | Installation done by third party and customer does not require installation. | IN | - |
| S52 | Product damaged, non-installable product, customer returned the product, or product gifted. | IN | - |
| S53 - S54 | Codes not in use. | - | - |
| S55 | Restriction on visit. | IN | - |
Select a cancellation reason code
- Call the
getServiceJobByServiceJobIdoperation and check for themarketplaceIdvalue to identify the marketplace details associated with the service order of a job. - Call the
getServiceJobByServiceJobIdoperation and check for theserviceTypevalue to identify the service type of the job.- If
serviceTypeisheavybulky, then search for a reason code in the Heavy Bulky column. - Otherwise, search for a reason code in the Default column.
- If
- Select a reason code suitable for your use case and pass it as a query parameter when you request a job for cancellation.
Updated 22 days ago
