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:
setAppointmentFulfillmentData
sets data such as fulfillment date-times, resources, and fulfillment document identifiers.createServiceDocumentUploadDestination
creates an upload destination for fulfillment documents such as Proof Of Appointment (POA) files.completeServiceJobByServiceJobId
sets a service job as completed.cancelServiceJobByServiceJobId
sets 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
NotServiced
state. - 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
createServiceDocumentUploadDestination
operation. - 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 theInputStream
method of theUploadToDestinationExample
class.
b. TheinitializationVector
andkey
values from thecreateServiceDocumentUploadDestination
response as arguments for theiv
andkey
parameters of theEncryptionDetails
method of theEncryptionDetails
class.
c. Theurl
value from thecreateServiceDocumentUploadDestination
response as the argument for theurl
parameter of theuploadToDestination
method of theUploadToDestinationExample
class. - Save the
sha256sum
value to pass as theContentSha256
parameter 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
getServiceJobByServiceJobId
operation and check for themarketplaceId
value to identify the marketplace details associated with the service order of a job. - Call the
getServiceJobByServiceJobId
operation and check for theserviceType
value to identify the service type of the job.- If
serviceType
isheavybulky
, 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 about 20 hours ago